Jaka jest różnica między
public
,private
iprotected
dziedziczenia w C ++?
Wszystkie pytania, które znalazłem w SO, dotyczą konkretnych przypadków.
c++
inheritance
encapsulation
access-specifier
c++-faq
Arsen Khachaturyan
źródło
źródło
SomeBase
jest po prostu sztywnym sposobem na skomponowanie anonimowego członka typuSomeBase
. To, jak każdy inny członek, ma specyfikator dostępu, który ma taką samą kontrolę nad dostępem zewnętrznym.WAŻNA UWAGA: wszystkie klasy B, C i D zawierają zmienne x, y i z. To tylko kwestia dostępu.
O korzystaniu z chronionego i prywatnego dziedzictwa można przeczytać tutaj .
źródło
Ograniczenie widoczności dziedziczenia spowoduje, że kod nie będzie mógł zobaczyć, że niektóre klasy dziedziczą inną klasę: niejawna konwersja z pochodnej do bazy nie będzie działać, a
static_cast
z bazy do pochodnej nie będzie działać.Tylko członkowie / przyjaciele klasy mogą widzieć prywatne dziedzictwo, a tylko członkowie / przyjaciele i klasy pochodne mogą widzieć chronione dziedzictwo.
dziedzictwo publiczne
Dziedziczenie IS-A. Przycisk jest oknem i wszędzie tam, gdzie potrzebne jest okno, można również przekazać przycisk.
chronione dziedzictwo
Chronione zaimplementowane zgodnie z warunkami. Rzadko przydatne. Używany w
boost::compressed_pair
celu czerpania z pustych klas i oszczędzania pamięci przy użyciu pustej optymalizacji klas podstawowych (przykład poniżej nie używa szablonu, aby być na bieżąco):spadek prywatny
Wdrożono w kategoriach. Zastosowanie klasy podstawowej służy wyłącznie do implementacji klasy pochodnej. Przydatne w przypadku cech i jeśli rozmiar ma znaczenie (puste cechy, które zawierają tylko funkcje, wykorzystają optymalizację pustej klasy podstawowej). Często jednak lepszym rozwiązaniem jest powstrzymywanie . Rozmiar ciągów ma krytyczne znaczenie, dlatego jest to często spotykane zastosowanie
członek publiczny
Agregat
Akcesoria
członek chroniony
Zapewnienie rozszerzonego dostępu dla klas pochodnych
członek prywatny
Zachowaj szczegóły implementacji
Zauważ, że rzutowanie w stylu C celowo pozwala rzutować klasę pochodną na chronioną lub prywatną klasę bazową w określony i bezpieczny sposób, a także rzucić w innym kierunku. Należy tego unikać za wszelką cenę, ponieważ może on uzależnić kod od szczegółów implementacji - ale w razie potrzeby można skorzystać z tej techniki.
źródło
Te trzy słowa kluczowe są również używane w zupełnie innym kontekście, aby określić model dziedziczenia widoczności .
W tej tabeli zebrano wszystkie możliwe kombinacje modelu deklaracji i modelu dziedziczenia przedstawiające wynikowy dostęp do komponentów, gdy podklasa jest całkowicie zdefiniowana.
Powyższa tabela jest interpretowana w następujący sposób (spójrz na pierwszy wiersz):
Przykład:
Uzyskany dostęp do zmiennych
p
,q
,r
w klasie Subsub jest żaden .Uzyskany dostęp do zmiennych
y
,z
w klasie Sub jest chroniony i dla zmiennejx
jest żaden .Teraz pozwala zdefiniować podklasę:
Zdefiniowana klasa o nazwie Sub, która jest podklasą klasy o nazwie
Super
lub taSub
klasa jest pochodnąSuper
klasy. DoSub
klasy wprowadza ani nowych zmiennych ani nowe funkcje. Czy to oznacza, że jakikolwiek obiektSub
klasy dziedziczy wszystkie cechy po tym, jakSuper
klasa jest w rzeczywistości kopią obiektówSuper
klasy?Nie . Tak nie jest.
Jeśli skompilujemy następujący kod, otrzymamy tylko błędy kompilacji, mówiąc, że
put
iget
metody są niedostępne. Dlaczego?Gdy pominiemy specyfikator widoczności, kompilator zakłada, że zastosujemy tak zwane dziedziczenie prywatne . Oznacza to, że wszystkie publiczne składniki nadklasy zamieniają się w prywatny dostęp, prywatne składniki nadklasy w ogóle nie będą dostępne. Oznacza to w związku z tym, że nie wolno używać tego ostatniego w podklasie.
Musimy poinformować kompilator, że chcemy zachować wcześniej używaną politykę dostępu.
Obiekty
Sub
klasy mogą robić „prawie” te same rzeczy, co ich starsze rodzeństwo utworzone zSuper
klasy. „Prawie”, ponieważ fakt bycia podklasą oznacza również, że klasa utraciła dostęp do prywatnych elementów nadklasy . Nie możemy napisać funkcjiSub
składowej klasy, która byłaby w stanie bezpośrednio manipulować zmienną pamięci.To bardzo poważne ograniczenie. Czy istnieje jakieś obejście?
Tak .
Trzeci poziom dostępu nazywa się chroniony . Słowo kluczowe chronione oznacza, że oznaczony nim komponent zachowuje się jak publiczny, gdy jest używany przez jedną z podklas i wygląda jak prywatny dla reszty świata . - Dotyczy to tylko klas dziedziczonych publicznie (takich jak klasa Super w naszym przykładzie) -
Jak widać w przykładowym kodzie, mamy nową funkcjonalność dla
Sub
klasy i robi ona jedną ważną rzecz: uzyskuje dostęp do zmiennej pamięci z klasy Super .Nie byłoby to możliwe, gdyby zmienna została zadeklarowana jako prywatna. W głównym zakresie funkcji zmienna i tak pozostaje ukryta, więc jeśli napiszesz coś takiego:
Kompilator poinformuje Cię, że jest to plik
error: 'int Super::storage' is protected
.Wreszcie ostatni program wygeneruje następujące dane wyjściowe:
źródło
Ma to związek z tym, jak publiczni członkowie klasy podstawowej są narażeni na działanie klasy pochodnej.
Jak wskazuje litb, dziedziczenie publiczne jest tradycyjnym dziedzictwem, które można zobaczyć w większości języków programowania. To znaczy modeluje relację „IS-A”. Dziedziczenie prywatne, coś, co AFAIK jest specyficzne dla C ++, to relacja „WDROŻONE W WARUNKACH”. Oznacza to, że chcesz korzystać z interfejsu publicznego w klasie pochodnej, ale nie chcesz, aby użytkownik klasy pochodnej miał dostęp do tego interfejsu. Wielu argumentuje, że w tym przypadku należy agregować klasę podstawową, czyli zamiast mieć klasę bazową jako bazę prywatną, w elemencie pochodnym w celu ponownego wykorzystania funkcjonalności klasy bazowej.
źródło
Typ dziedziczenia : Obiekt odziedziczony jako :
źródło
1) Dziedziczenie publiczne :
za. Prywatni członkowie klasy podstawowej nie są dostępni w klasie pochodnej.
b. Chronieni członkowie klasy podstawowej pozostają chronieni w klasie pochodnej.
do. Członkowie publiczni klasy podstawowej pozostają publiczni w klasie pochodnej.
Tak więc inne klasy mogą korzystać z publicznych elementów klasy Base za pośrednictwem obiektu klasy Derived.
2) Dziedziczenie chronione :
za. Prywatni członkowie klasy podstawowej nie są dostępni w klasie pochodnej.
b. Chronieni członkowie klasy podstawowej pozostają chronieni w klasie pochodnej.
do. Publiczni członkowie klasy Base również stają się chronionymi członkami klasy Derived.
Tak więc inne klasy nie mogą używać publicznych członków klasy Base za pośrednictwem obiektu klasy Derived; ale są dostępne dla podklasy pochodnej.
3) Dziedziczenie prywatne :
za. Prywatni członkowie klasy podstawowej nie są dostępni w klasie pochodnej.
b. Chronieni i publiczni członkowie klasy Base stają się prywatnymi członkami klasy Derived.
Zatem do innych klas klasy Base nie można uzyskać dostępu przez inne klasy za pośrednictwem obiektu klasy Derived, ponieważ są one prywatne w klasie Derived. Zatem nawet podklasa klasy pochodnej nie może uzyskać do nich dostępu.
źródło
Dziedziczenie publiczne modeluje związek IS-A. Z
każdy
D
jestB
.Dziedziczenie prywatne modeluje relację IMPLEMENTOWANĄ-UŻYTKOWĄ (lub jakkolwiek to się nazywa). Z
a nie
D
jestB
, ale każdyD
używa jejB
w jego realizacji. Prywatne dziedziczenie można zawsze wyeliminować, używając zamiast tego zabezpieczenia:To
D
również można zrealizować za pomocąB
, w tym przypadku za pomocą jegob_
. Ograniczenie jest mniej ścisłym sprzężeniem między typami niż dziedziczenie, więc ogólnie powinno być preferowane. Czasami stosowanie ograniczania zamiast dziedziczenia prywatnego nie jest tak wygodne, jak dziedziczenie prywatne. Często jest to kiepska wymówka dla lenistwa.Nie sądzę, żeby ktokolwiek wiedział, jakie
protected
modele dziedziczenia. Przynajmniej nie widziałem jeszcze żadnego przekonującego wyjaśnienia.źródło
D
wywodzi się prywatnieD
, może zastąpić funkcje wirtualneB
. (Jeśli, na przykład,B
jest interfejsem obserwatora, wówczasD
mógłby go zaimplementować i przekazaćthis
do funkcji wymagających takiego interfejsu, bez możliwości korzystania z niego przez wszystkichD
jako obserwatora.)D
Może również selektywnie udostępnić członkówB
swojego interfejsu poprzez działanieusing B::member
. Oba są niewygodne pod względem składniowym, gdyB
są członkami.protected
dziedziczenie, które uznałem za przydatne w przypadkuvirtual
klasy podstawowej iprotected
ctor:struct CommonStuff { CommonStuff(Stuff*) {/* assert !=0 */ } }; struct HandlerMixin1 : protected virtual CommonStuff { protected: HandlerMixin1() : CommonStuff(nullptr) {} /*...*/ }; struct Handler : HandlerMixin1, ... { Handler(Stuff& stuff) : CommonStuff(&stuff) {} };
Jeśli dziedziczysz publicznie po innej klasie, wszyscy wiedzą, że dziedziczysz i każdy może używać polimorficznie przez wskaźnik klasy bazowej.
Jeśli odziedziczysz w sposób chroniony, tylko twoje dzieci będą mogły korzystać z ciebie polimorficznie.
Jeśli odziedziczysz prywatnie, tylko ty będziesz mógł wykonywać metody klas nadrzędnych.
Co w gruncie rzeczy symbolizuje wiedzę reszty klas na temat twojego związku z klasą nadrzędną
źródło
Dostęp do chronionych danych mogą uzyskać wszystkie klasy, które dziedziczą po twojej klasie. Prywatni członkowie danych nie mogą jednak. Powiedzmy, że mamy następujące elementy:
Od wewnątrz rozszerzenia do tej klasy odwołania
this.myPrivateMember
nie będą działać. Jednakthis.myProtectedMember
będzie. Wartość ta jest wciąż enkapsulowana, więc jeśli mamy instancję tej klasy o nazwiemyObj
, tomyObj.myProtectedMember
nie będzie działać, więc działa podobnie do prywatnego członka danych.źródło
Na podstawie tego przykładu dla java ... Myślę, że stolik wart tysiąca słów :)
źródło
Podsumowanie:
Podczas dziedziczenia możesz (w niektórych językach) zmienić typ ochrony członka danych w określonym kierunku, np. Z chronionego na publiczny.
źródło
Prywatny:
Dostęp do prywatnych członków klasy podstawowej mogą uzyskać tylko członkowie tej klasy podstawowej.
Publiczny:
Członkowie publiczni klasy bazowej mogą uzyskać dostęp do członków tej klasy bazowej, członków jej klasy pochodnej, a także członków spoza klasy podstawowej i klasy pochodnej.
Chroniony:
Dostęp do chronionych członków klasy podstawowej mogą mieć członkowie klasy podstawowej oraz członkowie jej klasy pochodnej.
W skrócie:
prywatny : baza
chroniony : podstawa + pochodny
public : baza + pochodna + dowolny inny członek
źródło
Znalazłem łatwą odpowiedź i dlatego pomyślałem o opublikowaniu jej również w przyszłości.
Jest z linków http://www.learncpp.com/cpp-tutorial/115-inheritance-and-access-specifiers/
źródło
Zasadniczo jest to ochrona dostępu publicznego i chronionych członków klasy podstawowej w klasie pochodnej. Dzięki dziedziczeniu publicznemu klasa pochodna może widzieć publicznych i chronionych członków bazy. W przypadku dziedziczenia prywatnego nie może. W trybie chronionym klasa pochodna i wszystkie klasy pochodne od niej mogą je zobaczyć.
źródło