2016-02-02 18 views
6

Dieses Beispielprogramm zeigt, wie ein anderer Konstruktor aufgerufen wird, abhängig davon, ob Sie eine lokale Variable, eine globale Variable oder eine anonyme Variable übergeben. Was geht hier vor sich?C++ anonymer Konstruktor macht seltsame Dinge

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

Da ich globalStr.puke() nennen kann, vermute ich, dass aClass(globalStr); durch den Aufruf, es wird eine lokale Variable globalStr vom Typ aClass Namen erstellen, die anstelle der globalen globalStr verwendet wird. Der Aufruf von aClass(localStr); versucht dasselbe zu tun, aber es wird nicht kompiliert, weil localStr bereits als std::string deklariert ist. Ist es möglich, eine anonyme Instanz einer Klasse zu erstellen, indem Sie ihren 1-arg-Konstruktor mit einem nicht konstanten Ausdruck aufrufen? Wer hat entschieden, dass type(variableName); eine akzeptable Möglichkeit sein sollte, eine Variable namens variableName zu definieren?

+0

Was ist ein _anonymous Konstruktor_ ?? Mir ist nichts bewusst. –

+0

[Nun, das ist interessant] (http://ideone.com/eNXYvI), warum 'kotze()' in einer Klasse 'std :: string' aufgerufen werden kann. –

+1

@ πάνταῥεῖ, Es ist beschattet von der Deklaration von 'globalStr' in' main'. – chris

Antwort

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

Dieser versucht, eine Variable vom Typ aClasslocalStr genannt zu erklären. Die Syntax ist schrecklich, stimme ich zu, aber dafür ist es jetzt viel zu spät [den Standard ändern].

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

Dies erklärt ein globalStr genannt. Diese globalStr Variable verbirgt die globale.

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

Dadurch entsteht ein temporäres Objekt vom Typ aClass.

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

Dies erstellt auch eine temporäre.

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

Dies nutzt die globalStr in main, die mit jedem anderen Fall der Abschattung im Einklang steht.

Ist es möglich, eine anonyme Instanz einer Klasse zu erstellen, indem Sie ihren 1-arg-Konstruktor mit einem nicht konstanten Ausdruck aufrufen?

Ja, ich kann auf vier verschiedene Arten denken:

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. 

Als Randbemerkung, diese Syntax oft die Ursache für die meisten Vexing Parse sein kann. Zum Beispiel erklärt die folgende Funktion foo die aClass, mit einem Parameter localStr vom Typ gibt std::string:

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

der Tat ist es die gleiche Regel, die für Ihre Probleme verantwortlich ist - Wenn etwas kann als eine gültige Erklärung analysiert werden, es muss sein. Deshalb ist aClass(localStr); eine Deklaration und keine Aussage, die aus einem einzelnen Ausdruck besteht.