2009-07-14 13 views
5

C++ lässt keine Polymorphie für Methoden zu, die auf ihrem Rückgabetyp basieren. Beim Überladen einer impliziten Konvertierungselementfunktion scheint dies jedoch möglich.Warum funktionieren implizite Umsetzungselementfunktionen beim Überladen nach Rückgabetyp, während dies für normale Funktionen nicht zulässig ist?

Weiß jemand warum? Ich dachte, Operatoren werden intern wie Methoden behandelt.

Edit: Hier ist ein Beispiel:

struct func { 
    operator string() { return "1";} 
    operator int() { return 2; } 
}; 

int main() { 
    int x = func(); // calls int version 
    string y = func(); // calls string version 
    double d = func(); // calls int version 
    cout << func() << endl; // calls int version 
} 
+0

Können Sie ein Beispiel nennen? Ich bin nicht sicher, was Sie meinen, indem Sie nach Rückgabetyp überladen. –

+0

Würden Sie ein Beispiel geben? – jkeys

Antwort

11

Konvertierungsoperatoren werden nicht wirklich als unterschiedliche Überladungen betrachtet und sie werden nicht basierend auf ihrem Rückgabetyp aufgerufen. Der Compiler wird sie nur dann verwenden, wenn sie hat (wenn der Typ inkompatibel ist und konvertiert werden sollte) oder wenn explizit aufgefordert wird, einen von ihnen mit einem Umwandlungsoperator zu verwenden.

Semantisch, was Ihr Code ist dabei mehr verschiedene Typumwandlung Betreiber und nicht Überlastungen eines einzigen Betreibers zu erklären.

+0

"_Conversion-Operatoren werden nicht wirklich als unterschiedliche Überladungen betrachtet_" Sie sind überhaupt keine überladenen Funktionen: Sie haben unterschiedliche Namen. – curiousguy

3

Das ist nicht Art zurück. Das ist Typumwandlung.

Betrachte: func() erstellt ein Objekt vom Typ func. Es gibt keine Zweideutigkeiten, welche Methode (Konstruktor) aufgerufen wird.

Die einzige Frage, die bleibt, ist, wenn es möglich ist, es auf die gewünschten Typen zu werfen. Sie haben den Compiler mit der entsprechenden Konvertierung versehen, also ist es glücklich.

0

Überladungsauflösung wählt zwischen mehreren Kandidatenfunktionen aus. In diesem Prozess wird der Rückgabetyp der Kandidaten tatsächlich nicht berücksichtigt. Im Fall von Konvertierungsoperatoren ist jedoch der "Rückgabetyp" von entscheidender Bedeutung, um zu bestimmen, ob dieser Operator überhaupt ein Kandidat ist.

+0

Diese Kandidatenfunktionen haben unterschiedliche Rückgabetypen und auch ** andere Namen **. Sie sind nicht überlastet, beim Rückgabetyp noch weniger überlastet. – curiousguy

+0

@curiousguy: Konvertierungsfunktionen können bei cv-qualification und template-ness überladen werden. – MSalters

+0

Das ist richtig, aber in diesem speziellen Beispiel sind sie nicht überladen. – curiousguy

1

Es gibt keinen technischen Grund, die Überlastung von Funktionen in den Ergebnistypen zu verhindern. Dies wird in einigen Sprachen wie Ada zum Beispiel getan, aber im Kontext von C++, das auch implizite Konvertierungen (und zwei Arten von ihnen) hat, wird das Dienstprogramm reduziert, und die Interaktionen beider Merkmale würden schnell zu Mehrdeutigkeiten führen.

Beachten Sie, dass die Tatsache, dass implizite Konvertierungen sind benutzerdefinierbare zu simulieren Überlastung auf Ergebnistyp verwenden:

class CallFProxy; 
CallFProxy f(int); 

class CallFProxy { 
    int myParameter; 
    CallFProxy(int i) : myParameter(i) {} 
public: 
    operator double() { std::cout << "Calling f(int)->double\n"; return myParameter; } 
    operator string() { std::cout << "Calling f(int)->string\n"; return "dummy"; } 
}; 
+0

"_Es gibt nicht wirklich einen technischen Grund, die Überlastung von Funktionen in den Ergebnistypen zu verhindern._" Nun, der "technische Grund" ist, dass ein Funktionsaufruf in C++ (und nicht in Ada) einen wohldefinierten Typ hat. Fast alle Ausdrücke in C++ haben einen wohldefinierten Typ und Bedeutung, mit Ausnahme von (1) bedeutungslosen Unterausdrücken in einem Elementfunktionsaufruf in "o.mf()", "o.mf" ist kein gültiger Unterausdruck und tut dies auch keinen Typ haben (wenn 'mf' eine Mitgliedsfunktion ist, kein Datenelement); (2) Adresse einer überladenen Funktion, z. '& std :: cos' (' cos (float) ',' cos (double) ', ...?) – curiousguy

+0

(...) Um in C++ die Bedeutung eines Ausdrucks zu bestimmen, können Sie mit den inneren Teilausdrücken beginnen, ihre Bedeutung bestimmen und weitergehen (mit den oben erwähnten Ausnahmen). In Ada kann die Bedeutung von 'read()' vom Typ von 'var' in:' var: = read(); 'abhängen. Beachten Sie, dass 'read();' keine gültige Anweisung ist: In Ada gibt es keine Ausdruckanweisung. Sie müssen entweder eine Prozedur aufrufen (** nicht ** eine Funktion!), Oder eine Aufgabe ausführen. – curiousguy