2012-10-03 14 views
11

Przeciążam dwukrotnie operatora przy użyciu tej samej listy parametrów. ale z innym Zwraca typ:C++ operator przeciążenia dwa razy, jeden powrotny non-const reference i drugi const reference, jakie jest preferencje?

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

Więc kiedy dzwonię do operatora(), która byłaby funkcja o nazwie na podstawie tego co preferencji lub sytuacji? Wiem, że jeśli wywołuję() pod funkcją const, musi to być stała T &.

Ciekaw jestem, jak C++ radzi sobie z taką sytuacją i jak działa domyślna preferencja.

Dzięki

+1

Termin jest przeciążenie * *, i nie. – chris

+2

C++ Dezaktywuje przeciążenie według typu zwracanego. Można przejść do tego, co "może/powinien" zrobić, ale to nie ma znaczenia. Jedna z nich polega na tym, aby metoda stała, gdy typ powrotu jest stały, ponieważ może być przeciążony. Moja pamięć jest preferowana przez metodę const, a niestanowiącą nazwy const, nie byłaby legalna. – Joe

Odpowiedz

21

Te funkcje nie przeciążają się nawzajem; mają te same sygnatury, a więc próbę przedefiniowania tej samej funkcji, co jest błędem. Typ zwracany nie jest częścią podpisu funkcji. Aby przeciążyć funkcję, musisz zadeklarować drugą funkcję o tej samej nazwie, ale inne parametry lub kwalifikatory - to znaczy kwalifikatory funkcji, a nie typ zwracany.

(Nie zastępują się nawzajem, nadpisywanie jest tym, co klasy pochodne robią z ich wirtualnymi funkcjami klasy podstawowej).

Powszechne jest definiowanie przeciążenia funkcji składowej const i non-const; przeciążenie const musi zadeklarować funkcję const, nie tylko typ zwracany:

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

Teraz pierwszy zostanie wywołana, jeśli stosuje () do niebędącego const obiektu, a druga na const obiektu. Na przykład:

Thingy nc; 
Thingy const c; 

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

@ DavidRodríguez-dribeas: OK, nie zdawałem sobie sprawy, że "podpis" zawiera typ zwrotu. Czy istnieje oficjalny termin określający "bity, które określają, jakie obciążenie wybrać?" –

+0

@ DavidRodríguez-dribeas Może możesz to wyjaśnić, ponieważ wydaje się, że zmieniło się od C++ 03. "§1.3.18" zdaje się odnosić do funkcji szablonu. Jednak wpisy dla funkcji innych niż szablonowe (bezpłatne lub członkowskie) nie zawierają wzmianki o wartościach zwracanych. Nie ma także wpisów dotyczących specjalizacji funkcji szablonu. – juanchopanza

+0

@juanchopanza: Masz rację, usuwając komentarz. Mike, ostrożne ponowne przeczytanie standardu wskazuje, że dla szablonów funkcji (jak wspomina Juancho) typ zwracany jest częścią podpisu. W przypadku zwykłych funkcji podpis nie zawiera typu zwrotu. C++ 03 ma przypis: * Sygnatury funkcji nie zawierają typu zwracanego, ponieważ to nie bierze udziału w przeciążeniu. * Przepraszamy za wprowadzenie zamieszania do odpowiedzi :) –

3

nie można przeciążać funkcję/metodę opartą na typ zwracany. Spodziewam się, że kompilator rzuci tutaj błąd. Co można zrobić, to określić samej metody jako metody const korzystając

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

The const kwalifikatora oznacza nie tylko to można nazwać na odbiorniku const, ale to również jest używany w rozdzielczości przeciążenia. Dzieje się tak, ponieważ wpływa na niejawny parametr, który jest przekazywany do metody; Metoda const używa kwalifikatora const na,, a kwalifikatory są brane pod uwagę podczas rozwiązywania przeciążenia.

1

Sposób definiowania operatorów, nie sposób kompilator może zdecydować, który operator() zadzwonić. Przeciążanie funkcji (i operatorów) może być wykonywane tylko na typie argumentów, nigdy na typie zwracanym. I faktycznie, będziesz mieć błąd przy kompilacji, gdy tylko zdefiniujesz drugi, kompilator, biorąc pod uwagę, że zmieniasz definicję tej samej funkcji/operatora.

Jednakże następujące jest powszechne (i prawdopodobnie to, co masz):

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

Ten dodatkowy „const” po liście argumentów istnieje, ponieważ definiowania non-statyczne funkcje składowe i funkcje składowe mają niejawna ukryty argument: "ten" wskaźnik do instancji klasy. Słowo kluczowe "const" wskazuje tam, czy ten ukryty wskaźnik ma postać const, czy nie.Argument ten bierze udział w przeciążaniu rozdzielczości i to w tym przypadku jest to, czego używa kompilator, aby wybrać wersję operatora do użycia.

Więc:

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

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