2017-01-14 6 views
0

Ich habe eine Klasse, die verschiedene Arten von Variablen erstellt.Falscher Konstruktor wird aufgerufen

Und durch einige Makrodefinitionen wollen wir diese Variablen initialisieren.

Zahlen sind initialisiert, aber Strings rufen den Bool-Konstruktor aus unbekannten Gründen auf.

JsonVariable(string x) 
    : type(String), s(x) 
{ 
    cout << "String" << x << endl; 
    sleep 
} 
JsonVariable(bool x) 
    : type(Boolean), b(x) 
{ 
    cout << "Boolean" << x << endl; 
    sleep 
} 

Wenn ich den Bool-Konstruktor auskommentiere, dann wird die String-Eins aufgerufen.

Irgendwelche Vorschläge?

EDIT: Dies ist ein String-Konstruktor mit den definierten Makros. std :: string wird im Konstruktor verwendet.

JSON(test) = STRING("Hello") 

Typ ist eine definierte Enum. Auch Makros müssen als Teil dieser Zuweisung verwendet werden.

EDIT2: Zur Verdeutlichung. Hier ist der Enum-Typ.

std :: string wird mit Namespace std und somit single string verwendet. Auch ist String vom Typ ENUM so

String != string 

typedef enum { 
    Null, Integer, Double, Boolean, String, Object, Array 
} datatype; 
+2

Nennen Sie es mit einem echten String oder 'const char *' (wie '" myString "')? – lorro

+0

Ist dies 'JsonVariable (String x) : Typ (String), s (x)' kompilieren? –

+2

Außerdem warum verwenden Sie macors –

Antwort

2

Als Faustregel gilt, wenn Ihre API überladenen Funktionen oder Konstrukteuren dieser Signatur (oder dessen CV qualifizierte und/oder Bezugsvarianten) aussetzt:

für const char*
void func(std::string){} 
void func(bool){} 

Sie sollten immer liefern die eine,

void func(std::string){} 
void func(bool){} 
void func(const char* c){ func(std::string(c)); } 

, was Sie und Ihre Benutzer (vor allem) in seinen für subtilen suprises weil:

String-l Iterale (z. B. "abc...") zerfällt schnell zu const char* und durch Überladung Auflösung hat die Umwandlung zu bool eine höhere Priorität als eine benutzerdefinierte Umwandlung was ist, was std::string tut.

+1

Je nachdem, was Sie tun, möchten Sie vielleicht 'func (std :: string)' rufen 'func (const char *)' statt, über '.c_str()'. z.B. Im Beispiel des OP sehe ich keine Notwendigkeit für die String-Konstruktion. –

+1

Das funktioniert, const Char * Konstruktor heißt. Aber wie die Leichtigkeit erwähnt, beseitigt dies die Notwendigkeit für die Konstruktion von Saiten. Danke beiden. – Davelis4

3

Sie könnten die Wirkung von Konvertierungsregeln erfahren. Wenn Sie ein const char* übergeben, wird bool Überlastung über std::string& bevorzugt:

void f(std::string&) { std::cout << "string"; } 
void f(bool) { std::cout << "bool"; } 

int main() { 
    f("abc"); // prints 'bool' 
} 

Dies ist logisch: Zeiger werden in der Regel für seine Nicht-Null geprüft, so Umstellung auf int/bool Typen wünschenswert. Andererseits bedeutet das Binden an einen const std::string& einen std::string Erbauer und unter Bezugnahme. Eine Bindung an std::string& ist hier unmöglich, da Provisorien nicht an nicht-konstante Referenzen binden.

Workaround ist entweder manuell eine Zeichenfolge erstellen oder vorzugsweise einen Konstruktor für const char*.

+0

Hier gibt es kein Casting. –

+0

@LightnessRacesinOrbit: danke, korrigierte Terminologie (s/Casting/Konvertierung /). – lorro

+1

'f (" abc ");' wird nie 'f (std :: string &)' aufrufen, auch ohne Überladung, weil Sie kein temporäres an ein nichtkonstantes Zeichen binden können, sollten Sie ein 'const' hinzufügen. – Holt

Verwandte Themen