Es mag nicht offensichtlich erscheinen, aber es gibt zwei benutzerdefinierte Konvertierungen im Fall der Kopie-Initialisierung:
Foo f1 = "einige Zeichenkette";
In obigem Ausdruck ist Foo f1 =
ein Aufruf von Foo(Foo const &)
mit der rechten Seite als Argument. Dafür müsste der Compiler herausfinden, wie er von einem Literal (Array von N Zeichen) zu Foo
gelangen kann, und das erfordert eine benutzerdefinierte Konvertierung zu std::string
(Konstruktor, der const char*
übernimmt) und eine zweite benutzerdefinierte Konvertierung von std::string
zu Foo
(zweiter oben stehender Konstruktor).
Jetzt mag es nicht offensichtlich erscheinen, warum der zweite Fall nicht die gleiche Anzahl an Konvertierungen erfordert... wenn Sie Foo f("etwas");
machen, betrachtet der Compiler die drei Überladungen:
Foo(int);
Foo(std::string);
Foo(Foo const &);
Es gibt keine Konvertierung von Literal zu int
, daher wird der erste verworfen. Es gibt eine Ein-Schritt-Konvertierung von Literal zu std::string
(durch den Konstruktor, der const char*
übernimmt), also ist dies ein gültiger Kandidat. Wie oben zu sehen gibt es keine Ein-Schritt-Konvertierung von Literal zu Foo
, also wird auch diese verworfen und nur der einzige mögliche Kandidat ausgewählt.
Die Sprache ist ziemlich klar, dass es nur eine benutzerdefinierte Konvertierung in einer Konvertierungsfolge geben kann, also gibt es nichts, was dort getan werden kann. Sie sind also entweder darauf beschränkt, einen weiteren Konstruktor bereitzustellen oder sicherzustellen, dass die rechte Seite tatsächlich ein std::string
ist. Dafür könnten Sie entweder explizit konvertieren (gültig in C++03):
Foo f1 = std::string("etwas");
Sie könnten dies auch einfach dem Benutzer überlassen und verlangen, dass er die direkte Initialisierung anstelle der Kopie-Initialisierung durchführt. Oder Sie können einen Konstruktor hinzufügen, der den const char*
annimmt.