2012-12-14 15 views
153

O ile rozumiem, wprowadzenie słowa kluczowego override w C++ 11 nie jest niczym więcej niż sprawdzeniem, aby upewnić się, że zaimplementowana funkcja jest funkcją klasy podstawowej w postaci override.Czy słowo kluczowe "przesłonięcie" jest tylko sprawdzeniem zastępowanej metody wirtualnej?

Czy to prawda?

+42

Tak.⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣⁣ –

+11

To nie jest jednak podwójne sprawdzenie. To jedyny czek. –

+0

@Nikos dobry punkt;), naprawiony – aiao

Odpowiedz

183

To jest rzeczywiście pomysł. Chodzi o to, że są jawne, co masz na myśli, tak, że w przeciwnym razie milczy błąd może być zdiagnozowane:

struct Base 
{ 
    virtual int foo() const; 
}; 

struct Derived : Base 
{ 
    virtual int foo() // whoops! 
    { 
     // ... 
    } 
}; 

Powyższy kod kompiluje, ale nie jest to, co można mieć na myśli (nota brakującą const). Jeśli zamiast tego powiesz, virtual int foo() override, otrzymasz błąd kompilatora, że ​​twoja funkcja w rzeczywistości niczego nie przesłoni.

+51

+1: Niestety, jest to trochę czerwony śledzia, kiedy ludzie sugerują, że nowa funkcja "przesłonięcia" "naprawia" to; musisz pamiętać, aby go użyć, tak jak powinieneś pamiętać aby napisać 'const';) –

+0

Po prostu zdałem sobie sprawę, że definicje klasy" explicite "nie zostały wprowadzone do C++ 11. Huh. – aschepler

+1

@aschepler A co by zrobiła definicja "wyraźnej" klasy? W ogóle o tym nie słyszałem. –

23

Wikipedia Cytat:

Korekcja specjalny identyfikator oznacza, że ​​kompilator sprawdzi klasę bazową (es) aby sprawdzić, czy istnieje wirtualna funkcja z tą dokładną sygnaturą. A jeśli nie, kompilator będzie się mylił.

http://en.wikipedia.org/wiki/C%2B%2B11#Explicit_overrides_and_final

Edit (próbując poprawić nieco odpowiedź):

deklarujących metodę jako „ręcznym” oznacza, że ​​ta metoda przeznaczone przepisać (wirtualny) metoda na klasa podstawowa. Metoda nadrzędna musi mieć tę samą sygnaturę (przynajmniej dla parametrów wejściowych), co metoda, którą zamierza przepisać.

Dlaczego jest to konieczne? Cóż, zapobiega się następującym dwóm typowym błędom:

  1. jeden błąd tworzy typ w nowej metodzie. Kompilator, nieświadomy, że zamierza napisać poprzednią metodę, po prostu dodaje ją do klasy jako nową metodę. Problem polega na tym, że stara metoda wciąż istnieje, nowa jest dodawana jako przeciążenie. W takim przypadku wszystkie połączenia w kierunku starej metody będą działać tak, jak poprzednio, bez żadnych zmian w zachowaniu (które byłyby celem nadpisywania).

  2. zapomina się zadeklarować metodę w superklasie jako "wirtualną", ale wciąż próbuje ponownie zapisać ją w podklasie. Chociaż zostanie to najwyraźniej zaakceptowane, zachowanie nie będzie dokładnie takie, jak było to zamierzone: metoda nie jest wirtualna, więc dostęp przez wskaźniki do superklasy zakończy się wywołaniem starej (nadklasy) metody zamiast nowej (podklasy) metody.

Dodanie „override” wyraźnie disambiguates to: przez to, jedna mówi kompilatorowi, że trzy rzeczy są spodziewa:

  1. istnieje metoda o tej samej nazwie w nadklasą
  2. to metoda w nadklasie jest zadeklarowana jako "wirtualna" (co oznacza, że ​​ma być przepisana)
  3. metoda w nadklasie ma ten sam (wejściowy *) podpis jak metoda w podklasie (metoda przepisywania)

Jeśli którakolwiek z tych wartości jest nieprawidłowa, zostanie zgłoszony błąd.

* uwaga: parametr wyjściowy jest czasami inny, ale powiązany. Przeczytaj o przekształceniach kowariantnych i przeciwstawnych, jeśli są zainteresowane.

18

Znaleziono "przesłanianie" jest przydatne, gdy ktoś zaktualizował sygnaturę metody wirtualnej klasy podstawowej, np. Dodając opcjonalny parametr, ale zapomniał zaktualizować sygnaturę metody pochodnej klasy. W takim przypadku metody między klasą podstawową i pochodną nie są już zależne od polimorfizmu. Bez deklaracji zastąpienia trudno jest znaleźć tego rodzaju błąd.

+0

+1. Chociaż podczas gdy 'override' jest świetnym sposobem na odkrycie takich problemów, dobrym rozwiązaniem powinien być także dobry test testów jednostkowych. –

+0

Właśnie dlatego jestem tak podekscytowany tym nowym specyfikatorem. Jedynym problemem jest to, że ta funkcja musi być już zastosowana, aby zapobiec błędom powodowanym przez zmiany w klasach bazowych. ;-) – Wolf

Powiązane problemy