2016-02-02 21 views
6

Ten przykładowy program pokazuje, w jaki sposób zostanie wywołany inny konstruktor w zależności od tego, czy przekazujesz zmienną lokalną, globalną czy anonimową. Co tu się dzieje?C++ anonimowy konstruktor robiący dziwne rzeczy

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. 
} 

Biorąc pod uwagę, że mogę zadzwonić globalStr.puke(), zgaduję, że dzwoniąc aClass(globalStr);, to tworzy lokalną zmienną o nazwie globalStr typu aClass który jest używany zamiast globalnego globalStr. Wywołanie aClass(localStr); próbuje zrobić to samo, ale nie można go skompilować, ponieważ localStr jest już zadeklarowane jako std::string. Czy można utworzyć anonimową instancję klasy, wywołując jej konstruktor 1-arg z wyrażeniem niestałym? Kto zdecydował, że type(variableName); powinien być akceptowalnym sposobem zdefiniowania zmiennej o nazwie variableName?

+0

Co to jest _anonimowy konstruktor_ ?? Nie znam czegoś takiego. –

+0

[Cóż, to jest interesujące] (http://ideone.com/eNXYvI), dlaczego można wywołać 'puke()' na klasie 'std :: string'. –

+1

@ πάνταῥεῖ, Jest zacieniony deklaracją 'globalStr' w' main'. – chris

Odpowiedz

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

Ten próbuje zadeklarować zmienną typu aClass nazwie localStr. Składnia jest okropna, zgadzam się, ale teraz jest już za późno na to [zmiana standardu].

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

To oświadczenie o nazwie globalStr. Ta zmienna globalStr ukrywa globalną. To jest obiekt tymczasowy typu .

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

Powoduje to również utworzenie tymczasowego.

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

używa globalStr w main, który jest zgodny z każdym innym przypadku cieniowania.

Czy można utworzyć anonimową instancję klasy, wywołując jej konstruktor 1-arg z wyrażeniem niestałym?

Tak, myślę, że z czterech sposobów:

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. 

Na marginesie, to składnia może być często przyczyną najbardziej irytujących przetworzenia. Na przykład, co następuje deklaruje funkcję foo zwracającą aClass, z jednym parametrem localStr typu std::string:

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

Rzeczywiście to ta sama zasada, która jest odpowiedzialna za swoje problemy - Jeśli coś może być analizowany jako nieważny, to musi być. Dlatego aClass(localStr); jest deklaracją, a nie oświadczeniem składającym się z samotnego wyrażenia.