2 Stimmen

Gibt es eine Möglichkeit, die implizite Konstruktorinitialisierung mit einem Zeichenfolgenliteral zu erzwingen?

Angenommen, ich habe eine Klasse

class Foo
{
public:
    Foo(int x);
    Foo(std::string s);
}

Ich möchte Objekte so initialisieren können

int main()
{
    Foo f1 = "some string"
}

anstatt

int main()
{
    Foo f1("some string");
}

Bisher erhalte ich einen Compilerfehler: error: invalid conversion from 'const char*' to 'int' [-fpermissive]|

Alles, woran ich denken kann, ist, einen zusätzlichen Konstruktor zu erstellen, der ein char* Argument akzeptiert, aber ich hatte gehofft, diese Redundanz zu vermeiden.

2voto

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.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X