2013-08-12 21 views
102

Jestem początkujący w C++. Napotkałem słowo kluczowe override użyte w pliku nagłówkowym, nad którym pracuję. Czy mogę wiedzieć, jakie jest rzeczywiste użycie override, być może na przykładzie będzie to łatwe do zrozumienia.Do czego służy słowo kluczowe "zastąp" w C++?

+0

Należy również zauważyć, C++ 11 wprowadził 'final' słowa kluczowego. –

+8

@JesseDobry i jeszcze raz: 'final' __also nie jest słowem kluczowym__ !!! – zaufi

+1

@zaufi: Tak, nauczyłem się czegoś nowego. I + 1ed twoją odpowiedź. –

Odpowiedz

185

override kluczowe służy dwóm celom: „Jest to sposób wirtualnego, to jest przesłanianie wirtualnego metodę klasy bazowej”

  1. pokazuje czytnikiem kodu
  2. Kompilator wie również, że jest to przesłonięcie, więc może "sprawdzić", że nie zmieniasz/dodawanie nowych metod, które uważasz, że są przesłonięte.

Aby wyjaśnić ten ostatni:

class base 
{ 
    public: 
    virtual int foo(float x) = 0; 
}; 


class derived: public base 
{ 
    public: 
    int foo(float x) override { ... do stuff with x and such ... } 
} 

class derived2: public base 
{ 
    public: 
    int foo(int x) override { ... } 
}; 

W derived2 kompilator wyda błąd dla "zmieniając typ". Bez override, co najwyżej kompilator dałby ostrzeżenie "ukrywasz wirtualną metodę o tej samej nazwie".

+0

nie powinien nagłówek funkcji dla * foo * być podobny w klasie * deriv2 * ?? Skompilowałem to za pomocą VS2017 i otrzymałem błąd kompilacji. Mam na myśli to, że w * deriv2 * * nagłówek foo * musi być: * int foo (float x) override {...} * –

+8

Uhm, to w całości kwestia, przykład kodu pokazuje, jak można użyć override do wykrycia błędu! –

+0

Myślę, że # 3 jest to, że zastąpienie może być używane do wykrywania funkcji, która ma zostać zastąpiona (należąca do klasy/interfejsu nadrzędnego) jest usuwana (niezmienna). Jest to użyteczne, jeśli podklasa oczekuje wywołania zwrotnego, ale nigdy nie stanie się tak ze względu na zmianę biblioteki, itp. – Hei

4

override to słowo kluczowe C++ 11, które oznacza, że ​​metoda jest "przesłonięciem" metody z klasy bazowej. Rozważmy następujący przykład:

class Foo 
    { 
    public: 
     virtual void func1(); 
    } 

    class Bar : public Foo 
    { 
    public: 
     void func1() override; 
    } 

Jeśli B :: func1() podpis nie jest równa A :: func1() podpis błąd kompilacji zostanie wygenerowany ponieważ B :: func1() nie nadpisać :: func1(), zamiast tego zdefiniuje nową metodę o nazwie func1().

+5

Zgodnie ze specyfikacją C++, "przesłonięcie" jest "identyfikatorem o specjalnym znaczeniu". Ale takie rzeczy w języku C# są nazywane słowami kontekstowymi. –

0

Wikipedia mówi:

Metoda nadrzędnym, programowania obiektowego, to funkcja języka, który pozwala podklasą lub dziecko klasa zapewnienie konkretnej realizacji metody, które zostały podane przez jednego z jego nadrzędnych lub klasy nadrzędne.

W szczególności, gdy masz foo obiektu, który ma pustkę Hello() Funkcja:

class foo { 
    virtual void hello(); // Code : printf("Hello!"); 
} 

dzieckiem foo, będzie mieć również Hello() Funkcja:

class bar : foo { 
    // no functions in here but yet, you can call 
    // bar.hello() 
} 

Możesz jednak wydrukować "Hello Bar!" gdy funkcja hello() jest wywoływana z obiektu paska. Można to zrobić za pomocą nadpisanie

class bar : foo { 
    virtual void hello() override; // Code : printf("Hello Bar!"); 
} 
+4

Nie potrzebujesz identyfikatora nadpisania, aby zrobić to w C++, to po prostu wymusza, że ​​robisz to poprawnie. – Goose

43

i jako dodatku do wszystkich reaguje, FYI: overridenie jest słowem kluczowym, ale specjalny rodzaj identyfikatora! Ma znaczenie tylko w kontekście deklarowania/definiowania funkcji wirtualnych, w innych kontekstach jest to po prostu porządkowy numer identyfikator. Aby uzyskać szczegółowe informacje, przeczytaj 2.11.2 z Standard.

// kate: hl C++11; 
#include <iostream> 

struct base 
{ 
    virtual void foo() = 0; 
}; 

struct derived : base 
{ 
    virtual void foo() override 
    { 
     std::cout << __PRETTY_FUNCTION__ << std::endl; 
    } 
}; 

int main() 
{ 
    base* override = new derived(); 
    override->foo(); 
    return 0; 
} 

wyjściowa:

[email protected] /work/tests $ g++ -std=c++11 -o override-test override-test.cc 
[email protected] /work/tests $ ./override-test 
virtual void derived::foo() 
+3

Działa (tu i na końcu), ponieważ nie można używać zwykłych identyfikatorów, w których umieszczane są te słowa kluczowe kontekstowe. – CTMacUser

+0

dlaczego do diabła nie jest zabronione? –

+2

@FerencDajka 1. Dlaczego to powinno być? 2. Nagłe dodanie nowego słowa kluczowego (tj. Zabraniające używania go wszędzie indziej) złamałoby kompatybilność wsteczną. – idmean