2009-10-12 17 views
9

Derleme zamanında bir dizi dizi oluşturmanın kolay bir yolunu arıyorum. Ben başarıyla böyle bir kod derlemek bu kullanmaVirgül operatörünü kötüye kullanma

Strings(); 
Strings(const Strings& that); 
Strings(const char* s1); 
Strings& operator=(const char* s1); 
Strings& operator,(const char* s2); 

:

Strings s; 
s="Hello","World!"; 

s="Hello" parçası döndüren operator= çağıran bir test için, aşağıdaki üyesi vardır Strings adında bir sınıf araya Strings& ve ardından operator,, "World!" için çağrılır. Ben (MSVC, henüz başka derleyiciler denemedim) işe alınamıyor ne

olduğunu

Strings s="Hello","World!"; 

Ben Strings s="Hello" kopya kurucu çağırır ve sonra her şey hareket ettiği buraya varsaymak istiyorum ilk örnekle aynı. Ama hatayı alıyorum: error C2059: syntax error : 'string'

Ancak bu iyi çalışır:

Strings s="Hello"; 

Yani kopya yapıcı bir dize için en az çalışır biliyoruz. Herhangi bir fikir? Kodun biraz daha temiz olmasını sağlamak için ikinci yöntemin çalışmasını gerçekten çok isterim.

+8

Wow, virgül operatörünün aşırı yüklenmesiyle ilgili çok fazla şaka duydum. Asla birisinin aslında ** yapmasını beklemiyordum. –

+2

@Carl: (şey OP istediği çok benzeri) – UncleBens

+0

* titreme * Kendi içinde çivi koymak http://www.boost.org/doc/libs/1_40_0/libs/assign/doc/index.html#intro hakkında ne tabut. Yanlış gitmeye başladığında nasıl hata ayıklayacaksınız? –

cevap

14

Sanırım ikinci örneğindeki virgül, virgül operatör değil, çoklu değişken bildirimleri için dilbilgisi öğesidir.

örneğin yazabilirsiniz aynı şekilde:

Strings s="Hello", stringliteral 

Yani derleyici olarak virgülden sonra öğeyi bekler:

int a=3, b=4 

Bu aslında yazıyoruz geliyor bana bir değişkenin adı ve bunun yerine bir dizgi değişmezini görür ve bir hatayı bildirir. Başka bir deyişle, kurucu "Merhaba" a uygulanır, ancak daha sonra virgül Dizginin virgül operatörüdür. Bu arada, kurucu gerçekten bir kopya oluşturucu değildir. Bir değişmez dize parametresinden bir Strings nesnesi oluşturur ... Kopya yapıcısı terimi genellikle aynı türe uygulanır.

+2

. Kopya ctorunun callable olmasını ve hatta geçici bir nesneden 's' inşasını gerektiriyor. Ancak, 'const char *' kurucusunun 's' için herhangi bir geçici olmaksızın doğrudan başlatılması ile değiştirilmesinin en uygun hale getirilmesine izin verilir ve ortaktır. –

+0

Duh, bunu görmediğime inanamıyorum. – miked

8

Bu tür bir API'yi tavsiye etmem. Beklendiği gibi çalışmayan vakaları keşfetmeye devam edersiniz, çünkü virgül en düşük öncelikli operatördür.Örneğin, bu durumda da işe yaramayacağını:

if ("Hello","world" == otherStrings) { ... } 

Sen dizeleri kümesi etrafında her zaman desteklerini kullanıyorsanız bu gibi işlerin daha mümkün olabilir:

Strings s=("Hello","World!"); 

Ve benim yukarıdaki örnek şuna benzer:

olasılıkla işe yapılabilir
if (("Hello","world") == otherStrings) { ... } 

ama steno sözdizimi muhtemelen onunla birlikte gelen zor semantik değmez.

+3

Bu işe yarayabilir mi? Ben tahmin sorun 'yüzden,' const char * '' için operatörü, 'yüklenmeyin olmasıdır ("Merhaba", "dünya")' ' "dünya"' tıpkı aynıdır. –

+0

Operatörü aşırı yükleyebileceğinizi varsadım (const char *, const char *). Bunun yapılmaması için bir sebep var mı? Dürüst olmak gerekirse çok fazla C++ programlama yapmıyorum. –

0

Sen, karakter işaretçiler

Strings::Strings(const char* input[]); 

const char* input[] = { 
    "string one", 
    "string two", 
    0}; 

Strings s(input); 

ve kurucu içinde

bir dizi kullanmak Eğer null adlı çarpana kadar işaretçiler yinelemenize olabilir.

+0

ya da kurucu şablon: 'şablon dizeleri (const char * (ve giriş) [N]) {için (int i = 0; i

+0

Ah, ya elbette yapıcı şablonu farklı yerlerde farklı uzunluklarda dolu dersek yinelenen kod oluşturuluyor önlemek için, vektör :: ekin (yineleyici, InputIterator, InputIterator) '' benzer başka işlevi diyebiliriz. –

0

Eğer C++ 0x yaparsanız, bunun için yeni inializer lists var! Keşke bunları kullanabilseydin. Örneğin: Strings tek vazifesi dizeleri listesini saklamak için ise

std::vector<std::string> v = { "xyzzy", "plugh", "abracadabra" }; 
std::vector<std::string> v{ "xyzzy", "plugh", "abracadabra" }; 
0

ardından boost::assign ben yapmak mümkündür var :)

using namespace boost::assign; 
vector<string> listOfThings; 
listOfThings += "Hello", "World!"; 
1

düşünüyorum standart konteynerler ile iyi bir iş yapabilirdi Bu çalışma, "iş" in yeterince gevşek bir tanımı için. İşte bir kaç yıl önce benzer bir soruya yanıt olarak yazdığım bir çalışma örneği. Bu bir meydan okuma olarak eğlenceliydi, ama gerçek kodda kullanmazdım:

#include <iostream> 
#include <algorithm> 
#include <iterator> 
#include <vector> 

void f0(std::vector<int> const &v) { 
    std::copy(v.begin(), v.end(), 
     std::ostream_iterator<int>(std::cout, "\t")); 
    std::cout << "\n"; 
} 

template<class T> 
class make_vector { 
    std::vector<T> data; 
public: 
    make_vector(T const &val) { 
     data.push_back(val); 
    } 

    make_vector<T> &operator,(T const &t) { 
     data.push_back(t); 
     return *this; 
    } 

    operator std::vector<T>() { return data; } 
}; 

template<class T> 
make_vector<T> makeVect(T const &t) { 
    return make_vector<T>(t); 
} 

int main() { 
    f0((makeVect(1), 2, 3, 4, 5)); 
    f0((makeVect(1), 2, 3)); 
    return 0; 
} 
İlgili konular