2016-10-19 2 views
1

Ich habe eine Klasse in C++, und ich würde gerne in der Lage sein, ein Objekt zu drucken, also habe ich einen char * -Cast-Operator erstellt. Die Sache ist, dass aus irgendeinem Grund die Ausgabe der Operatorfunktion zufällige Symbole anstelle meiner zurückgegebenen Zeichenfolge ist. hier ist der Code:Zufallsausgabe mit char * -Operator

operator const char*()const { 
    std::cout << (std::to_string(Nom) + '/' + std::to_string(Denom)).c_str() << std::endl; 
    return (std::to_string(Nom) + '/' + std::to_string(Denom)).c_str(); 
} 

und die Hauptfunktion:

Rational r1(7, 15); 
std::cout << r1<<std::endl; 
return 0; 

Die erste Zeile Ausgabe normaly ("7/15"), aber der Rückgabewert nur zufällige Buchstaben.

Irgendwelche Hinweise?

+1

Was denken Sie, die c_str() tut? – UKMonkey

+3

Sie rufen 'c_str()' für ein temporäres Objekt auf. Das Ergebnis ist ein fliegender Zeiger in dem Moment, in dem Ihr Operator zurückkehrt. – StoryTeller

+0

Der Grund, dass 'std :: string' 'c_str()' und nicht 'operator char *()' hat, ist es offensichtlicher, dass Code wie dieser etwas ernsthaft falsch macht. –

Antwort

0

Eine Ergänzung zu anderen Antworten: Normalerweise ist ein impliziter Cast-Operator ein schlechter Stil. Vor allem eine Besetzung für einen Typ, der nicht mit dem Ihrer Klasse verwandt ist.

Wenn Sie Ihr Objekt werfen wollen, kann der bessere Weg, eine explizite Umwandlung sein:

class Rational 
{ 
public: 
    ... 
    std::string toString() const 
    { 
     return std::to_string(Nom) + '/' + std::to_string(Denom); 
    } 
}; 

Sie können damit eine „out“ Funktion überlasten:

std::ostream & operator <<(std::ostream &stream, const Rational &obj) 
{ 
    stream << obj.toString(); 
    return stream; 
} 

Wenn Sie nur Um Ihr Objekt auszublenden, können Sie auch eine Überladung ohne Cast-Funktion verwenden:

class Rational 
{ 
public: 
    ... 
    friend std::ostream & operator <<(std::ostream &stream, const Rational &obj) 
    { 
     stream << std::to_string(obj.Nom) + '/' + std::to_string(obj.Denom); 
     return stream; 
    } 
}; 
4

(std::to_string(Nom) + '/' + std::to_string(Denom)) erstellt eine temporäre Variable. Die .c_str() erhält die Adresse eines Speichers, der zu dieser Variablen gehört.

Kurz danach wird diese Variable zerstört (Sie kopieren oder verschieben sie nicht an eine beliebige Stelle). Die Erinnerung ist befreit.

Die Adresse, die Sie von c_str() erhalten haben, wird zwar beibehalten, aber jetzt zeigt es auf etwas Speicher, der jetzt Teil Ihrer Anwendung sein kann oder nicht. Der Versuch dies zu lesen ist Undefined Behavior (oder kurz UB auf dieser Seite).

3

Ersatz für die Rückgabe eines Objekts, das Speicher verwaltet, anstelle von einem const char*.

operator std::string() const { 
    std::stringstream ss; 
    ss << Nom << '/' << Denom; 
    return ss.str(); 
} 
+3

Wenn Sie den Operator const char * (statt std :: string) benötigen, behalten Sie eine Kopie der Zeichenfolge als Mitglied der Klasse, und Sie können dann die .c_Str() davon zurückgeben. – UKMonkey

+0

Ich würde weiter vorschlagen, die Zeichenkette zu einem "veränderlichen" Mitglied zu machen und einen veränderbaren "Status geändert" -Bool hinzuzufügen, so dass eine faule Bewertung und Zwischenspeicherung verwendet werden kann, ohne die Korrektheit der Klasse zu brechen. Dadurch können Sie die String-Erstellungslogik in den Operator einfügen, sodass die tatsächliche repräsentative Zeichenfolge nur beim ersten Aufruf des Operators generiert und nur aktualisiert wird, wenn der Status der Instanz seit dem letzten Aufruf geändert wurde. –

Verwandte Themen