2009-10-16 18 views
7

I dont całkowicie zrozumieć:prywatne dziedziczenie

class Base 
{ 
    public: 
    Base() 
    { 
     cout<<"Base" << endl; 
    } 

    virtual void call() 
    { 
     cout<<"Base call" << endl; 
    } 
}; 

class Derived: private Base 
{ 
    public:  
    Derived() 
    { 
     cout<<"Derived" << endl; 
    } 
}; 

int main(void) 
{ 
    Base *bPtr = new Derived(); // This is not allowed 
} 

Czy dlatego, że ktoś może zadzwonić do call() używając bPtr która jest faktycznie wykonywane na obiekcie pochodzi? Czy jest jakiś inny powód?

Odpowiedz

18

ze wspólnego zrozumienia dziedziczenia, C++”«prywatne dziedziczenie»to straszne mylące: to nie dziedziczenia (o ile wszystko poza klasą jest zaniepokojony) ale kompletny detal implementacja klasy.

Widziane z zewnątrz prywatne dziedziczenie to w zasadzie to samo, co kompozycja. Tylko wewnątrz klasy otrzymujesz specjalną składnię, która bardziej przypomina dziedziczenie niż kompozycję.

Istnieje jednak pewne zastrzeżenie: C++ traktuje je syntaktycznie jako dziedziczenie, z wszystkimi korzyściami i problemami, które się z tym wiążą, takimi jak scope visibility and accessibility. Ponadto odlewy C-style (! Ale nie C++ cast) faktycznie ignoruje widoczność i tym samym uda się odlewania wskaźnik Derived do Base:

Base* bPtr = (Base*) new Derived(); 

trzeba dodawać, że jest to zło.

+7

To dziedziczenie implementacji, a nie dziedziczenie interfejsu. –

+0

@ Laurence: prawda, ale to tylko kłóci się z terminologią. Byłem zainteresowany widokiem z zewnątrz na zajęcia. –

+1

"_it is not inheritance_" Absolutnie źle. Jest ** dziedziczeniem z dostępem prywatnym. – curiousguy

0

Prywatne dziedziczenie powoduje utratę możliwości traktowania obiektu pochodnego jako obiektu klasy podstawowej.

1

Jeśli dziedziczysz prywatnie, każdy kod wymagający konwersji z wersji pochodnej * na bazę * musi być członkiem lub przyjacielem klasy pochodnej.

+0

Dzięki za odpowiedzi, ale tak naprawdę chciałem wiedzieć, dlaczego nie dopuściły do ​​tego. –

+0

@nitinsoman Ponieważ ** ty ** napisałeś 'prywatny'. Tak prywatny dostęp oznacza ... jakie jest twoje pytanie? – curiousguy

9

Ponieważ private oznacza "szczegóły implementacji", co oznacza, że ​​Derived pochodzi od Base szczegółów implementacji.

Prywatne dziedziczenie nie jest dziedziczeniem interfejsu, ale dziedziczeniem implementacji. Nie implementuje relacji "Is-A", ale relację "Jest zaimplementowane-używanie". Derived nie jest Base w odniesieniu do użytkowników klas, po prostu dzieje się (obecnie) zaimplementowane przy użyciu tego.

+0

Niesamowite wytłumaczenie w tak małych zdaniach +1 –

17

dziedziczenie publiczny oznacza, że ​​każdy wie, że pochodne pochodzi z bazy.

Protected dziedziczenie oznacza, że ​​tylko pochodny, przyjaciół pochodnych, a zajęcia pochodzą z pochodnego wiedzieć, że pochodna jest pochodzący z bazy. *

Prywatne dziedziczenie oznacza, że ​​tylko pochodny i przyjaciele pochodnych wiedzieć, że pochodna jest pochodzące z bazy .

Ponieważ używasz prywatnego dziedziczenia, twoja funkcja main() nie ma pojęcia o wyprowadzeniu z bazy, a więc nie może przypisać wskaźnika.

Prywatne dziedziczenie jest zwykle używane do wypełniania relacji "jest zaimplementowany w warunkach". Jednym z przykładów może być to, że baza udostępnia wirtualną funkcję, którą należy przesłonić - a zatem musi być dziedziczona z - ale nie chcesz, aby klienci wiedzieli, że masz ten związek dziedziczenia.

* także: ile drewna miałoby wykonać uchwyt do drewna ...

+4

Trzy i pół roku później i dodatek do mojej odpowiedzi: w przypadku prywatnego dziedziczenia należy pamiętać, że nawet Baza nie wie, że Pochodny pochodzi od Bazy. Oznacza to, że 'dynamic_cast (this)' w funkcji składowej Base zawsze zwróci wartość NULL, jeśli Derived dziedziczy prywatnie z bazy. Wspominam o tym, ponieważ ostatnio przygryzł mnie on podczas próby prywatnego dziedziczenia klasy przekazanej za pośrednictwem Curiously Recursive Template Pattern. –