====== Dziedziczenie ( C++ ) ======

Dziedziczenie jest jednym z kluczowych założeń programowania zorientowanego obiektowo.

Dziedziczenie to mechanizm, który pozwala klasie przejmować właściwości (metody, atrybuty) innych klas. Dzięki temu nowe klasy muszą implementować jedynie dodatkowe właściwości (tworząc klasę wystarczy wskazać, czym różni się ona od już istniejącej). Właściwości zaimplementowane wcześniej będą dziedziczone i nie muszą być ponownie implementowane. Rozwiązanie takie umożliwia nie tylko redukcję rozmiarów kodu, ale pozwala także zachować jego spójność, ponieważ identyczne właściwości przestają pojawiać się w wielu miejscach kodu i sprawdzenie ich poprawności bądź modyfikacja wykonywana jest tylko raz.


**Klasa pochodna nie dziedziczy**:

* Konstruktorów

* Destruktorów

* Operatora przypisania

Konstruktor klasy bazowej nie posiada informacji o składowych zdefiniowanych w klasie pochodnej. Jeśli klasa pochodna nie zdefiniuje żadnego konstruktora, dostępny będzie konstruktor domyślny i kopiujący.

W wyniku braku informacji o składowych klasy pochodnej przypisanie byłoby niekompletne.
W klasie nie definiującej operatora przypisania dostępna jest jego domyślna implementacja generowana przez kompilator.

Jeśli w klasie podstawowej lub w klasach będących składowymi konstruktor kopiujący (operator przypisania) jest niedostępny (prywatny), to nie zostanie on wygenerowany domyślnie w klasie pochodnej.


** Hierarchie klas **

Dzięki dziedziczeniu klasy tworzą ściśle określoną hierarchię.

Klasa, która dziedziczy funkcjonalność innej klasy, nazywana jest klasą podrzędną (podklasą), natomiast klasa, z której dziedziczą inne klasy to klasa nadrzędna (klasa bazowa).


===== Maskowanie składowych =====

Obiekty mają dostęp do wszystkich metod i atrybutów ze swojej klasy oraz klas nadrzędnych (zgodnie ze specyfikatorami dostępu). Przykładowo, jeśli na danym obiekcie zostanie wywołana metoda, to interpreter sprawdza, czy jest ona zaimplementowana w klasie, z której pochodzi ten obiekt. Jeśli metoda nie zostanie odnaleziona to poszukiwania kontynuowane są w kolejnych klasach nadrzędnych.

W przypadku, gdy klasa podrzędna oraz nadrzędna definiują metodę o takiej samej nazwie, typie zwracanych wartości oraz argumentów to używana jest definicja, która została odnaleziona jako pierwsza. Dzięki temu, w danej klasie możliwe jest utworzenie metody, która będzie zapobiegała wywołaniu metody z klasy nadrzędnej (maskowanie metody).


==== Dostęp do składników ====

Struktura klasy zawiera słowa kluczowe, które grupują składowe ze względu na rodzaj dostępu. Słowa te pozwalają określić, które składowe są dostępne jedynie we wnętrzu klasy, a które także na zewnątrz.

Prywatne składowe klasy podstawowej (//private//) są dziedziczone (jak wszystkie inne składowe), ale w zakresie klasy pochodnej nie ma do nich bezpośredniego dostępu. Dostęp do nich uzyskuje się dzięki odziedziczonym nieprywatnym funkcjom składowym. 

Składniki nieprywatne (//protected//, //public//) są dostępne w zakresie klasy pochodnej. <del>Składowe protected w klasie bazowej zachowują się jak składowe public (publiczne, dostępne z zewnątrz), natomiast w klasie pochodnej jak private.</del>

Deklaracja klasy pochodnej również może mieć wpływ na sposób dziedziczenia i dostępność nieprywatnych składowych klasy bazowej. 

      class klasaPochodna : [dostęp] klasaBazowa {}

Opcjonalne słowo kluczowe dostępu umożliwia określenie zakresu dostępności dziedziczonych składowych.


**Private** (domyślnie) - dostęp do wszystkich składowych dziedziczonych po klasie bazowej staje się prywatny.

**Protected** - składowe opatrzone w klasie bazowej słowem kluczowym public stają się protected w klasie pochodnej, a protected i private zachowują swoje znaczenie z klasy bazowej.

**Public** - nie nakłada dodatkowych ograniczeń.


Wykorzystując //deklaracje dostępu// również można określić sposób dostępu do dziedziczonych składowych. Mimo, że występuje dziedziczenie prywatne wybrane składowe mogą być udostępnione jako public lub protected.

          class potomek : private przodek {
                  protected:
                           przodek::x;
                  public:
	                   przodek::y;
          };


Deklaracja dostępu może tylko powtórzyć dostęp, jaki składowa miała w klasie bazowej. Dotyczy jedynie niepublicznych składowych dziedziczonych prywatnie. Uniemożliwia rozróżnienie nazw przeładowanych (brak informacji o argumentach).

===== Dziedziczenie pojedyncze i wielokrotne =====

Mechanizm dziedziczenia zaimplementowany w języku Java jest nazywany dziedziczeniem pojedynczym, ponieważ klasa może mieć tylko jedną klasę nadrzędną (klasa nadrzędna może mieć wiele klas podrzędnych). W języku C++ klasy mogą posiadać więcej niż jedną klasę nadrzędną i w ten sposób dziedziczyć zmienne i metody od wszystkich klas nadrzędnych. Taki mechanizm jest nazywany dziedziczeniem wielokrotnym i pozwala na tworzenie klas o niemal dowolnych zachowaniach

===== Wirtualne klasy podstawowe =====

Jeśli klasa pochodna posiada kilka klas bazowych, może się okazać że niektóre z nich są pochodnymi (pośrednio lub bezpośrednio) tej samej klasy bazowej.
Aby składowa dziedziczona za pośrednictwem wielu klas pochodnych tej samej klasy bazowej była unikalna,  klasy pochodne muszą zadeklarować tę klasę bazową jako wirtualną klasę bazową.

----

----

===== O specyfikatorach dostępu raz jeszcze. =====

W uwagach są kontrowersje co do tego. Może ja postaram się to wyjaśnić jakoś jaśniej. Zaznaczam że to co piszę dotyczy **C++**.

**Dostęp do składowych (funkcji i obiektów) danej klasy określamy poprzez specyfikatory dostępu**:
  * public - składnik dostępny dla wszystkich,
  * protected - składnik dostępny dla tej klasy oraz dla wszystkich klas ją dziedziczących. Dla innych obiektów jest on niewidoczny.
  * private - składnik dostępny tylko dla danej klasy, klasy dziedziczące, ani tym bardziej "świat zewnętrzny" nie widzą go.

Oczywiście uwaga że można się dostać do składnika private przez nieprywatną funkcję pobierającą go jest jak najbardziej słuszna, ale - klasa musi taką funkcję posiadać, jak nie ma - składnik niedostępny. Innym sposobem do dostania się do składników private/protected są klasy i funkcje zaprzyjaźnione.

Jeśli nie wyspecyfikujemy dostępu, czyli napiszemy np. tak:

       class A {
            int x;
       public:
            int z;
       };

To składnik z jest oczywiście public, natomiast x jest private - bo domyślnym sposobem dostepu do składnika jest private.

Oprócz tego **przy dziedziczeniu danej klasy możemy określić jak będą dziedziczone jej składniki __nieprywatne__** (protected, public). 

Robimy to właśnie poprzez specyfikator określany przy definicji klasy pochodnej, czyli:

         class klasaPochodna : [dostęp] klasaBazowa {}

I teraz jeśli [dostęp] jest:
  * public - składniki public/protected zachowują dostęp z klasy bazowej (public jest nadal public, protexted nadal protected),
  * protected - składniki public stają się składnikami protected, a status składników protected nie ulega zmianie,
  * private - składniki public i protected stają się w klasie pochodnej składnikami private.

Czyli za pomocą tego modyfikatora określamy dostęp wszystkich składników public/protected dziedziczonych z klasy bazowej.

Tutaj podobnie jak przy składnikach klasy, domyślnym sposobem dziedziczenia składników jest private, czyli jeśli napiszemy:

        class A {}
        class B : A {}

to będzie tak jakbyśmy napisali:

        class B : private A {}

Jeśli nadal nie jest jasno wyjaśnione - piszcie w uwagach.

Jacek S. - autor powyższego paragrafu.
