2009-11-05 14 views
9

Jeśli mam w C++:C++ Wdrożenie funkcji wirtualnej?

class A { 
    private: virtual int myfunction(void) {return 1;} 
} 

class B: public A { 
    private: virtual int myfunction(void) {return 2;} 
} 

następnie, jeśli usunę virtual z definicji myfunction w class B, to znaczy, że gdybym miał class C podstawie class B, że nie mogę nadpisać myfunction ponieważ byłby statycznie skompilowany?

Jestem także zdezorientowany co do tego, co dzieje się, gdy przełączasz się tutaj na publiczne i prywatne. Jeśli zmienię definicję myfunction w class B na publiczną (a ta w class A pozostanie prywatna), czy jest to jakiś poważny błąd, którego nie powinienem robić? Sądzę, że funkcje wirtualne muszą być tego samego typu, więc jest to nielegalne, ale prosimy o informację, czy to źle.

Dzięki!

+5

Nie jest konieczne jawne zapisywanie słowa kluczowego "virtual" dla metod klas pochodnych. można go pominąć, ale jest to dobry styl, aby go mieć. – varnie

Odpowiedz

15

Pierwsza definicja z "wirtualnym" to ta, która ma znaczenie. Ta funkcja z bazy jest od tego momentu wirtualna, jeśli pochodzi od, co oznacza, że ​​nie potrzebujesz "wirtualnego" dla reimplementowanych wirtualnych wywołań funkcji. Jeśli sygnatura funkcji w klasie bazowej nie jest wirtualna, ale wirtualna w klasach pochodnych, wówczas klasa bazowa nie ma zachowania polimorficznego.

class Base 
{ 
    public: 
    void func(void){ printf("foo\n"); } 
}; 
class Derived1 : public Base 
{ 
    public: 
    virtual void func(){ printf("bar\n"); } 
}; 
class Derived2 : public Derived1 
{ 
    public: 
    /* reimplement func(), no need for 'virtual' keyword 
     because Derived1::func is already virtual */ 
    void func(){ printf("baz\n"); } 
}; 

int main() 
{ 
    Base* b = new Derived1; 
    Derived1* d = new Derived2; 

    b->func(); //prints foo - not polymorphic 
    d->func(); //prints baz - polymorphic 
} 
+0

Dzięki, to było bardzo pomocne! – ash

+0

Nie ma za co. Powinienem także dodać, że "Baza * b" jest w rzeczywistości pochodną1. Użyj dynamic_cast, aby wykonać bezpieczne downcasting w sytuacjach, gdy tego potrzebujesz. –

+0

Ale przykład autorów dotyczy członków prywatnych. – bua

1

Jeśli usuniesz virtual z definicją zawartą w klasie B myfunction,

kompilator doda to za Ciebie. Aby wypełnić tabelę V dla typów polimorficznych.

!! ALE !!

Będziesz miał dostęp do członków publicznych klasy A tylko (klasa B: public A)

definicja:

class B: private A 
{ 

} 

sprawi, że wszyscy (nawet publiczne) członkowie klasy A, będzie stać się prywatnym dla klasy B. Upraszcza Nie będziesz mieć dostępu do publicznych członków.

Aby obejść Można zadeklarować jakąś znajomego:

class A 
{ 
    private: 
     friend class B; 
} 

Więcej informacji HERE wielki.

+0

Dzięki za szybką odpowiedź! – ash

+0

Odpowiedź jest dla mnie nieco dezorientująca. Z odpowiedzi przeczytałem, że klasa B nie może uzyskać dostępu do publicznych członków, których dziedziczy po klasie A, która jest następnie rozwiązywana przez deklarację przyjaciela B A. Nie sądzę, żeby to było właściwe. B może uzyskać dostęp do publicznych i chronionych członków od A, ale użytkownicy B nie mogą uzyskać dostępu do publicznych członków A, a to nie zostanie rozwiązane przez deklarację przyjaciela. Czy nie rozumiem czegoś? – stefaanv

+0

Tak, przegapiłeś prywatne dziedzictwo z mojego przykładu. – bua

7

po tym, jak funkcja stanie się wirtualna w klasie bazowej, będzie ona wirtualna dla każdej innej podklasy.

publiczne, chronione i prywatne nie mają wpływu na wirtualny charakter funkcji.

+0

Dziękujemy! Dziękujemy za informacje o widoczności. – ash

+0

Dzięki temu, że Twoje funkcje wirtualne są chronione lub prywatne, możesz wskazać użytkownikom swojej klasy, czy muszą oni wywoływać je w podklasie, czy też nie. http://www.gotw.ca/publications/mill18.htm –

0

Zachowanie virtual jest to, że efekty, które metoda jest wywoływana, gdy masz wskaźnik jednego typu, który wskazuje na przedmiot podtyp. Na przykład:

B* obj = new B; 
A* base = obj; 

Co się dzieje, kiedy zadzwonić obj->myfunction() zależy od tego, czy A deklaruje myfunction być wirtualny. Jeśli nie jest wirtualny, rozumowanie jest następujące: mamy wskaźnik typu A, dlatego wywołujemy funkcję zdefiniowaną w A, a wynikiem jest 1.Jeśli jednak A definiuje wartość myfunction jako wirtualną, wówczas wykonywane jest wyszukiwanie w czasie wykonywania w oparciu o typ rzeczywistego obiektu, a nie typ wskaźnika; ponieważ obiekt jest w rzeczywistości B, stosowana jest implementacja zdefiniowana w B, a wynikiem jest 2.

Więcej informacji można znaleźć w the C++ FAQ Lite section on virtual functions.

Powiązane problemy