2015-12-31 7 views
8

Ich habe einen Code durchsucht, den ich für ein Schulprojekt geschrieben habe, das mir bei näherer Betrachtung merkwürdig erschien. Ich hatte eine Klasse ähnlich dem unten:Zurückdrücken der Zeichenfolge in den Vektor der Objekte

class Foo { 
public: 
    Foo(std::string s) : _s(s) {} 
private: 
    std::string _s; 
}; 

int main() { 
    std::string str = "Hiyo"; 

    std::vector<Foo> f; 
    f.push_back(str); // Compiles. Weird to me though. 
    f.push_back(Foo(str)); // Predictably, this compiles as well. 

    return 0; 
} 

Warum ist der erste Aufruf von push_back eine gültige Aussage, obwohl str ist kein Foo?

Antwort

16

Klasse Foo einen nicht explizit Ctor ein Argument des Typs std::string (d.h. Converting constructor), das heißt, es implizit aus einem std::string gegossen werden kann.

f.push_back(str);  // implicit casting from std::string to Foo 
f.push_back(Foo(str)); // explicit casting from std::string to Foo 

Hinweis, wenn Sie den Ctor explicit machen, wird das implizite Casting verboten.

class Foo { 
public: 
    explicit Foo(std::string s) : _s(s) {} 
// ~~~~~~~~ 
private: 
    std::string _s; 
}; 

und dann

f.push_back(str);  // invalid now 
f.push_back(Foo(str)); // still valid 
+1

Dies sollte die akzeptierte Antwort sein, da es sich um "explizit" handelt – CinCout

7

Das erste Zurückdrücken initialisiert automatisch ein Foo Objekt, das ein string Objekt erhält; durch Ihre Initialisierungsliste.

(erwartet ein Foo Objekt erhält einen String: kann ein Foo Objekt mit einer einzigen Zeichenfolge initialisiert wird Ja, hat seine Initialisiererliste einzelnes Element und das Objekt wird von diesem Elemente initialisiert).

Einzelheiten siehe z.B .:

+2

Die Initialisiererliste sollte nicht von Bedeutung sein. Wird immer noch ohne es kompilieren. – ChrisD

+1

Was ist, wenn 'Foo (std :: string s)' 'explizit' ist? – CinCout

2

Ich denke, dass es automatisch in der ersten Push-Back initialisiert ist Foo(str) So seine basicaly tha gleiche!