2011-06-18 16 views
11

Co oznacza słowo kluczowe wirtualne podczas przesłonięcia metody? Nie używam go i wszystko działa dobrze.Co oznacza słowo wirtualne podczas przesłaniania metody?

Czy każdy kompilator zachowuje się tak samo w tym zakresie?

Czy powinienem go używać, czy nie?

+0

możliwy duplikat [C++ Virtual/Pure Virtual Explained] (http://stackoverflow.com/questions/1306778/c-virtual-pure-virtual-explained) –

+0

@Harald: Nie. Inny temat. – Xeo

+0

Ale pytam o użycie tego słowa kluczowego. Nie o abstrakcyjnej wirtualnej metodzie. – kravemir

Odpowiedz

11

Nie można nadpisać funkcję składową bez niego.

Możesz tylko ukryć jeden.

struct Base { 
    void foo() {} 
}; 

struct Derived : Base { 
    void foo() {} 
}; 

Derived::foo robi nie nadpisanie Base::foo; to po prostu ukrywa go, ponieważ ma taką samą nazwę, taką, że:

Derived d; 
d.foo(); 

wywołuje Derived::foo.

virtual umożliwia polimorfizm taki, że faktycznie funkcje ręczne:

struct Base { 
    virtual void foo() {} 
}; 

struct Derived : Base { 
    virtual void foo() {} // * second `virtual` is optional, but clearest 
}; 

Derived d; 
Base& b = d; 
b.foo(); 

To wywołuje Derived::foo, bo to teraz nadpisaniaBase::foo — Twój obiekt jest polimorficzny.

(też mieć używać odniesień i wskazówek na to, ze względu na the slicing problem.)


  • Derived::foo nie trzeba powtarzać słowa kluczowego virtual ponieważ Base::foo już wykorzystane. Gwarantuje to standard i możesz na nim polegać. Jednak niektórzy uważają, że najlepiej zachować to dla jasności.
+2

Wiem, że wirtualny jest niezbędny podczas deklarowania metody, która może być nadpisana. Poprosiłem o użycie tego słowa kluczowego podczas przesłonięcia metody, a nie deklarowania. – kravemir

+1

@Miro: Nie śledzę. Nadpisujesz funkcję, deklarując inną, która ją zastępuje. Tak czy inaczej, mój ostatni akapit odpowiada na twoje pytanie. –

8

Metoda w klasie bazowej będzie kaskadowo przechodzić przez hierarchię, dzięki czemu każda metoda podklasy z tym samym podpisem będzie również oznaczona jako virtual.

class Base{ 
public: 
    virtual void foo(){} 
}; 

class Derived1 : public Base{ 
public: 
    virtual void foo(){} // fine, but 'virtual' is no needed 
}; 

class Derived2 : public Base{ 
public: 
    void foo(){} // also fine, implicitly 'virtual' 
}; 

Zalecam jednak napisanie virtual, ale tylko dla celów dokumentacyjnych.

5

Gdy funkcja jest wirtualna, pozostaje wirtualna w całej hierarchii, niezależnie od tego, czy jawnie określasz za każdym razem, gdy jest ona wirtualna. Kiedy przesłanianie metody, należy użyć wirtualnego aby być bardziej wyraźne - żadnej innej różnicy :)

class A 
{ 
    virtual void f() 
    { 
     /*...*/ 
    }; 
}; 

class B:public A; 
{ 
    virtual void f() //same as just void f() 
    { 
     /*...*/ 
    }; 
};