2013-05-01 4 views
8

diese 2 Funktionen gegeben, die ändern und geben einen String:Was garantiert, dass die überladene nicht-konstante Methode aufgerufen wird?

// modify the original string, and for convenience return a reference to it 
std::string &modify(std::string &str) 
{ 
    // ...do something here to modify the string... 
    return str; 
} 

// make a copy of the string before modifying it 
std::string modify(const std::string &str) 
{ 
    std::string s(str); 
    return modify(s); // could this not call the "const" version again? 
} 

Dieser Code funktioniert für mich GCC g ++ verwenden, aber ich verstehe nicht, warum/wie. Ich würde mir Sorgen machen, dass die zweite Funktion sich selbst nennen würde und mich mit einer außer Kontrolle geratenen Rekursion zurücklassen würde, bis der Stack erschöpft ist. Funktioniert das garantiert?

+0

Dies ist Endrekursion, am wahrscheinlichsten. Ich bin mir nicht sicher, ob die Semantik, einen const-ref-Aufruf in eine Schleife zu verwandeln, also keine Antwort zu posten, sondern die Tail-Rekursion nachschlägt und Sie mehr Informationen finden. – ssube

+2

@peachykeen: Nein, es ist überhaupt keine Rekursion. –

+0

Erwägen Sie, einen Titel auszuwählen, der die Frage besser fokussiert - z. "Was garantiert, dass die überladene nicht-konstante Methode aufgerufen wird?" – user2246674

Antwort

9

Sie zwei überladene Funktionen haben:

std::string &modify(std::string &str) 
std::string modify(const std::string &str) 

Was Sie vorbei ist ein nicht const qualifizierten std::string. Daher ist die Funktion, die das non const-qualified-Argument verwendet, besser geeignet. Wenn das nicht existierte, könnte der Compiler die non-const-qualifyed-Zeichenfolge in eine const-qualified-Zeichenfolge umwandeln, um den Aufruf durchzuführen, aber für die Funktionsüberlastung eines Aufrufs, der keine Konvertierung erfordert, passt besser als ein Aufruf, der a erfordert Umwandlung.

3
return modify(s); // could this not call the "const" version again? 

Nein, es ist nicht Rekursion. Es würde die andere Überladung aufrufen, deren Parameter std::string & ist.

Dies liegt daran, dass der Typ des Ausdrucks sstd::string & ist, der mit dem Parametertyp der anderen überladenen Funktion übereinstimmt.

Um recurse zu machen, muss das Argument an Call-Site in std::string const & umgewandelt werden. Aber in Ihrem Fall ist diese Umwandlung unnötig, da es eine Überlastung gibt, die keine Konvertierung erfordert.

1

Dies ist keine Rekursion, es ist überladen. Wenn Sie die zweite Funktion aufrufen, wird als Argument eine konstante Zeichenfolge verwendet. Innerhalb dieser Funktion rufen Sie die andere Funktion auf, die eine nicht konstante Zeichenfolge annimmt. Was Sie tun, ist das Strippen der Const-ness der Zeichenkette und eine bessere Weise, das zu tun, würde sein, const_cast zu verwenden.

I'll just link to this other stackoverflow thread.

+0

Ich möchte keine Konstanz entfernen. Das würde dazu führen, dass eine scheinbar konstante Zeichenkette modifiziert wird! –

+0

Was Sie tun können, ist die Zuweisung der nichtkonstanten Zeichenfolge, indem Sie etwas wie folgt tun: std :: string & str2 = const_cast (str). str bleibt konstant, aber du kannst str2 beliebig ändern. – Shaz

Verwandte Themen