2016-02-02 26 views
6

Bu örnek program, yerel değişkeni, genel değişkeni veya anonim değişkeni geçip geçmediğinize bağlı olarak farklı bir kurucunun nasıl çağrılacağını gösterir. Burada neler oluyor?C++ anonim yapıcı garip şeyler yapıyor

std::string globalStr; 
class aClass{ 
public: 
    aClass(std::string s){ 
    std::cout << "1-arg constructor" << std::endl; 
    } 
    aClass(){ 
    std::cout << "default constructor" << std::endl; 
    } 
    void puke(){ 
    std::cout << "puke" << std::endl; 
    } 
}; 

int main(int argc, char ** argv){ 
    std::string localStr; 
    //aClass(localStr); //this line does not compile 
    aClass(globalStr); //prints "default constructor" 
    aClass(""); //prints "1-arg constructor" 
    aClass(std::string("")); //also prints "1-arg constructor" 
    globalStr.puke(); //compiles, even though std::string cant puke. 
} 

ben aClass(globalStr); arayarak, küresel globalStr yerine kullanılan tipte aClass ait globalStr adında yerel bir değişken oluşturmak olduğunu tahmin ediyorum, globalStr.puke() çağırabilir göz önüne alındığında. aClass(localStr);'u çağırmak aynı şeyi yapmaya çalışır, ancak localStr zaten std::string olarak bildirilmiş olduğundan derleme başarısız olur. 1-arg yapıcısını sabit olmayan bir ifadeyle çağırarak bir sınıfın anonim bir örneğini oluşturmak mümkün mü? 'un variableName isimli bir değişken tanımlamak için kabul edilebilir bir yol olduğuna kim karar verdi?

+0

Ne bir _anonymous constructor_ nedir? Farkında olduğum bir şey yok. –

+0

[Pekala, bu ilginç] (http://ideone.com/eNXYvI), neden bir 'std :: string' sınıfında çağrılabilir puke(). –

+1

@ πάνταῥεῖ, "mainStr" in "main" olarak bildirilmesiyle gölgeleniyor. – chris

cevap

12
aClass(localStr); //this line does not compile 

Bu localStr adlı tip aClass bir değişken bildirmek çalışır. Sözdizimi korkunç, katılıyorum, ama şu an için bu standardın değişmesi çok geç.

aClass(globalStr); //prints "default constructor" 

Bu, globalStr adlı bildirir. Bu globalStr değişkeni genel olanı gizler.

aClass(""); //prints "1-arg constructor" 

Bu, aClass türünde geçici bir nesne oluşturur.

aClass(std::string("")); //also prints "1-arg constructor" 

Bu ayrıca bir geçici oluşturur.

globalStr.puke(); //compiles, even though std::string cant puke. 

Bu gölgeleme her örneği ile tutarlıdır main içinde globalStr kullanır.

1-arg yapıcısını sabit olmayan bir ifadeyle çağırarak, bir sınıfın anonim örneğini oluşturmak mümkün mü?

Evet, dört şekilde düşünebilirsiniz:
aClass{localStr}; // C++11 list-initialization, often called "uniform initialization" 
(void)aClass(localStr); // The regular "discard this result" syntax from C. 
void(aClass(localStr)); // Another way of writing the second line with C++. 
(aClass(localStr)); // The parentheses prevent this from being a valid declaration. 

Bir yan not olarak, bu sözdizimi genellikle çoğu Vexing Parse nedeni olabilir. Örneğin, aşağıdaki tek bir parametre ile, aClass döndüren bir işlev foo beyan tip std::string ait localStr:

aClass foo(std::string(localStr)); 

Nitekim o tüm sorunları sorumlu olduğunu aynı kural var - şey geçerli beyanı olarak çözümlenebilir, bunu olmalıdır. Bu nedenle aClass(localStr); bir beyan ve yalnız bir ifadeden oluşan bir ifade değildir.