Konstruiere ein Objekt mit einem String-Literal

8

Ich habe die folgende Klasse:

%Vor%

Ich suchte nach dem Grund, warum es ein Fehler ist, ohne Glück.

Ist es richtig, mit einem String-Literal zu konstruieren? wenn nein, warum? Wenn ja, was ist falsch an meinem Code?

Ich benutze gcc 5.3 mit Code :: Blocks 16.1.

    
Kamal Zidan 10.06.2017, 12:20
quelle

2 Antworten

11

Zuerst ist "4" nicht std::string , es ist const char[2] . Dann

CLS c("4"); ist direkte Initialisierung , die Konstruktoren von CLS werden auf die Initialisierung von% untersucht Code%. c wird hier aufgenommen, weil CLS::CLS(string) implizit in const char[] über benutzerdefinierte Konvertierung (d. h. std::string ) konvertiert werden kann.

std::string::string(const char*) ist Kopierinitialisierung ,

(Betonung meiner)

  
  • Wenn CLS d = "5"; ein Klassentyp ist und die cv-unqualifizierte Version des Typs T nicht other oder abgeleitet von T ist oder wenn T kein Klassentyp ist, aber der Typ von T ist ein Klassentyp, benutzerdefinierte Konvertierungssequenzen, die vom Typ other in other (oder in einen von T abgeleiteten Typ, wenn T konvertiert werden können) ist ein Klassentyp und eine Konvertierungsfunktion ist verfügbar) werden untersucht und die beste wird durch Überladungsauflösung ausgewählt.
  •   

Das bedeutet, dass benutzerdefinierte Konvertierungssequenzen benötigt werden, um T in const char[2] zu konvertieren. Sogar CLS könnte in const char[] konvertiert werden, und std::string könnte in std::string konvertiert werden, aber nur eine benutzerdefinierte Umwandlung ist in einem implizite Konvertierungssequenz . Deshalb wird es abgelehnt.

(Betonung meiner)

  

Implizite Konvertierungssequenz besteht aus folgendem in dieser Reihenfolge:

     

1) null oder eine Standardkonvertierungssequenz;
    2) null oder eine benutzerdefinierte Umwandlung;
    3) null oder eine Standard-Konvertierungssequenz.

BTW: Wenn Sie es so ändern, dass CLS explizit als Initialisierungsausdruck verwendet wird, funktioniert es einwandfrei. z.B.

%Vor%     
songyuanyao 10.06.2017, 13:08
quelle
8
%Vor%

a und c werden mit direkter Initialisierung initialisiert. b und d andererseits verwenden Initialisierung kopieren .

Der Unterschied besteht darin, dass der Compiler bei der Initialisierung der Kopie nach einer (einzelnen) benutzerdefinierten Konvertierung von (im Falle von d ) char const * (dies ist ein bisschen ungenau, siehe Ende der Antwort) nach CLS sucht. wohingegen für die direkte Initialisierung alle Konstruktoren versucht werden, wobei CLS(std::string) verwendet werden kann, da eine Konvertierung std::string(char const *) verfügbar ist.

Detail:

"5" ist ein (C) String-Literal. Der Typ ist char const [2] . Zuerst wird eine benutzerdefinierte Konvertierung von diesem Typ in CLS gesucht. Da keine gefunden wird, wird die Standardkonvertierung von Type[N] nach Type * (mit Type = char const und N = 2 ) angewendet, was zu char const * führt. Dann versucht der Compiler eine benutzerdefinierte Konvertierung von dieser in CLS zu finden. Da es keine findet und es keine Standardkonvertierungen gibt, die es ausprobieren könnte, schlägt die Kompilierung fehl.

    
Daniel Jour 10.06.2017 13:05
quelle