2012-10-03 6 views
11

Ich überladen einen Operator zweimal mit der gleichen Parameterliste. aber mit unterschiedlichem Rückgabetyp:C++ - Überlastoperator zweimal, eine Rückgabe nicht-const Referenz und die andere Konstante const, was ist die Präferenz?

T& operator()(par_list){blablabla}  
const T& operator()(par_list){blablabla} 

Also, wenn ich den Operator() bin Aufruf, die Funktion basierend auf welchen Vorlieben oder Situation genannt werden würde? Ich weiß, dass, wenn ich() unter const Funktion rufe, es die Konstante T & eins sein muss.

Ich bin nur neugierig, wie C++ mit einer solchen Situation umgehen und wie die Standardpräferenz funktioniert.

Dank

+1

Der Begriff ist * Überlastung * und Nr. – chris

+2

C++ Unterbindet Überlast nach Rückgabetyp. Man könnte gehen in das, was es tun könnte/sollte, aber es spielt keine Rolle. Ein Trick besteht darin, die Methode const zu machen, wenn der Rückgabetyp const ist, da dieser überladen werden kann. Mein Gedächtnis ist die const-Methode ist bevorzugt, mit non-const genannt const Call wäre nicht legal. – Joe

Antwort

21

Diese Funktionen überlasten sich nicht; sie haben die gleichen Signaturen, und so der Versuch, die gleiche Funktion neu zu definieren, was ein Fehler ist. Der Rückgabetyp gehört nicht zur Signatur einer Funktion. Um eine Funktion zu überlasten, müssen Sie eine zweite Funktion mit demselben Namen, aber anderen Parametern oder const/volatile Qualifiern deklarieren - also Qualifier für die Funktion, nicht den Rückgabetyp.

(Sie überschreiben sich auch nicht gegenseitig; das Überschreiben ist, was abgeleitete Klassen mit den virtuellen Funktionen ihrer Basisklassen machen).

Es ist üblich, eine const und eine nicht-const Überladung einer Elementfunktion zu definieren;

T& operator()(par_list){blablabla} 
const T& operator()(par_list) const {blablabla} 
           ^^^^^ 

nun die erste genannt wird, wenn Sie () zu einem nicht const Objekt und das zweite auf einem const Objekt anwenden: die const Überlastung muss die Funktion const, nicht nur die Rückgabetyp deklarieren. Zum Beispiel:

Thingy nc; 
Thingy const c; 

nc(); // calls the first (non-const) overload 
c(); // calls the second (const) overload 
+0

@ DavidRodríguez-dribeas: OK, ich habe nicht erkannt, "Signatur" inklusive Rückgabetyp. Gibt es einen offiziellen Begriff für "die Bits, die bestimmen, welche Überladung zu wählen"? –

+0

@ DavidRodríguez-dribeas Vielleicht können Sie dies klären, weil es sich seit C++ 03 geändert zu haben scheint. '§1.3.18' scheint sich auf Template-Funktionen zu beziehen. Aber die Einträge für Nicht-Vorlage (frei oder Mitglied) Funktionen erwähnen keine Rückgabewerte. Auch keine Einträge für Template-Spezialisierungen. – juanchopanza

+0

@juanchopanza: Sie haben Recht, den Kommentar entfernen. Mike, ein sorgfältiges erneutes Lesen des Standards zeigt an, dass für Funktionsschablonen (wie Juancho erwähnt) der Rückgabetyp Teil der Signatur ist. Bei regulären Funktionen enthält die Signatur nicht den Rückgabetyp. C++ 03 hat eine Fußnote: * Funktionssignaturen enthalten keinen Rückgabetyp, da dieser nicht an der Überladungsauflösung beteiligt ist. * Entschuldigung für die Verwirrung der Antwort :) –

3

Sie können keine Funktion/Methode auf Rückgabetyp basiert überlasten. Ich würde erwarten, dass der Compiler hier einen Fehler wirft. Was Sie tun können, ist die Methode selbst als const Methode angeben, können

const T& operator()(par_list) const {blahblah} 

Die const Qualifier bedeutet nicht nur mit diesem auf einem const Empfänger genannt werden, aber es ist auch in der Überladungsauflösung verwendet. Dies geschieht, weil es den impliziten Parameter *this betrifft, der an die Methode übergeben wird. Eine const Methode verwendet einen const Qualifier auf *this und const Qualifier werden bei der Überladungsauflösung berücksichtigt.

1

Die Art und Weisen Sie Ihre Betreiber definieren, keine Möglichkeit der Compiler den Operator() entscheiden können, zu nennen. Das Überladen von Funktionen (und Operatoren) kann nur für den Typ der Argumente erfolgen, niemals für den Rückgabetyp. Und tatsächlich, Sie werden einen Fehler bei der Kompilierung haben, sobald Sie den zweiten definieren, wobei der Compiler berücksichtigt, dass Sie die gleiche Funktion/den gleichen Operator neu definieren.

Allerdings ist die folgende gemeinsame (und wahrscheinlich das, was Sie haben):

T& operator()(par_list){blablabla} 
const T& operator()(par_list) const {blablabla} 

Diese zusätzliche „const“ nach der Argumentliste existiert, weil Sie nicht-statische Member-Funktionen und Elementfunktionen definieren haben eine implizite Verstecktes Argument: Der Zeiger "this" auf die Instanz der Klasse. Das Schlüsselwort "const" gibt an, ob sich dieser versteckte Zeiger auf eine konstante Instanz bezieht oder nicht.Dieses Argument ist an der Überladungsauflösung beteiligt, und in diesem Fall wählt der Compiler die zu verwendende Version des Operators aus.

So:

class A { 
    T& operator()() { ... } 
    const T& operator()() const { .... } 
}; 

A a; 
const A& ca(a); 
a(); -> returns a T& 
ca(); -> returns a const T&