Po co nam dziedziczenie prywatne lub chronione w C++?

W C++ nie przychodzi mi do głowy przypadek, w którym chciałbym dziedziczyć private / protected od klasa bazowa:

class Base;
class Derived1 : private Base;
class Derived2 : protected Base;
Czy to naprawdę przydatne?
Author: anonymous, 2008-12-17

7 answers

Jest to przydatne, gdy chcesz mieć dostęp do niektórych członków klasy bazowej, ale bez ujawniania ich w interfejsie klasy. Dziedziczenie prywatne może być również postrzegane jako pewien rodzaj kompozycji: C++ faq-lite daje następujący przykład, aby zilustrować to stwierdzenie

class Engine {
 public:
   Engine(int numCylinders);
   void start();                 // Starts this Engine
};

class Car {
  public:
    Car() : e_(8) { }             // Initializes this Car with 8 cylinders
    void start() { e_.start(); }  // Start this Car by starting its Engine
  private:
    Engine e_;                    // Car has-a Engine
};

Aby uzyskać ten sam semantyczny, możesz również napisać klasę samochodu w następujący sposób:

class Car : private Engine {    // Car has-a Engine
 public:
   Car() : Engine(8) { }         // Initializes this Car with 8 cylinders
   using Engine::start;          // Start this Car by starting its Engine
}; 
Jednak ten sposób działania ma kilka wad:
  • twoje intencje są znacznie mniej Wyczyść
  • może prowadzić do nadużycia wielokrotnego dziedziczenia
  • łamie enkapsulację klasy silnika, ponieważ możesz uzyskać dostęp do jego chronionych członków
  • możesz zastąpić wirtualne metody silnika, co jest czymś, czego nie chcesz, jeśli twoim celem jest prosta kompozycja
 42
Author: Luc Touraille,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-18 09:02:09

Prywatne mogą być przydatne w wielu okolicznościach. Tylko jedna z nich to polityka:

Czy częściowa specjalizacja szablonu klasy jest odpowiedzią na ten problem projektowy?.

Inną okazją, gdzie jest to przydatne, jest zabronienie kopiowania i przypisywania:

struct noncopyable {
    private:
    noncopyable(noncopyable const&);
    noncopyable & operator=(noncopyable const&);
};

class my_noncopyable_type : noncopyable {
    // ...
};

Ponieważ nie chcemy, aby użytkownik miał wskaźnik typu noncopyable* do naszego obiektu, pobieramy prywatnie. To się liczy nie tylko dla nie do skopiowania, ale także dla wielu innych tego typu klas (polisy są najczęściej spotykane).

 39
Author: Johannes Schaub - litb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:40

Modele dziedziczenia publicznego to-A.
Niepubliczne modele dziedziczenia są-implementowane-w-kategoriach-
Modele Przechowawcze mają-A, co jest równoważne IS-IMPLEMENTED-in-TERMS-OF.

Sutter na temat . Wyjaśnia, kiedy wybrałbyś Niepubliczne dziedziczenie zamiast zabezpieczenia dla szczegółów implementacji.

 15
Author: Greg Rogers,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-17 14:21:14

Na przykład, gdy chcesz ponownie użyć implementacji, ale nie interfejsu klasy i nadpisać jej funkcje wirtualne.

 3
Author: Nemanja Trifunovic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-17 16:01:34

Dziedziczenie prywatne jest najczęściej używane z niewłaściwego powodu. Ludzie używają go do zaimplementowania w kategoriach, jak wskazano we wcześniejszej odpowiedzi, ale z mojego doświadczenia wynika, że zawsze bardziej czyste jest zachowanie kopii niż dziedziczenie z klasy. Inna wcześniejsza odpowiedź, ta o CBigArray, stanowi doskonały przykład tego anty-wzoru.

Zdaję sobie sprawę, że mogą być przypadki, gdy has-a nie działa z powodu zbyt gorliwego użycia "protected" , ale lepiej naprawić zepsutą klasę niż złamać nową klasy.

 3
Author: Arkadiy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-18 14:50:13

Użyłem zarówno dziedziczenia prywatnego, jak i chronionego w pewnym momencie.

Private inheritence jest przydatne, gdy chcesz, aby coś miało zachowanie klasy bazowej, a następnie było w stanie nadpisać tę funkcjonalność, ale nie chcesz, aby cały świat był tego świadomy i używał go. Możesz nadal używać interfejsu klasy prywatnej, korzystając z funkcji zwracającej ten interfejs. Jest to również przydatne, gdy możesz mieć rzeczy rejestrują się, aby słuchać wywołań zwrotnych, ponieważ mogą rejestrować się za pomocą prywatnego interfejsu.

Protected inheritence jest szczególnie przydatne, gdy masz klasę bazową, która wywodzi użyteczną funkcjonalność z innej klasy, ale chcesz, aby jej pochodne mogły jej używać.

 0
Author: Daemin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-17 16:03:51

Kiedyś zaimplementowałem te struktury danych jako klasy:

  • Linked list
  • Generic array (abstract)
  • Simple array (inherits from generic array)
  • Big array (inherits from generic array)

Interfejs Wielkiej tablicy sprawiał, że wyglądała ona jak tablica, jednak w rzeczywistości była to powiązana lista prostych tablic o stałej wielkości. Więc zadeklarowałem to tak:

template <typename T>
class CBigArray : public IArray, private CLnkList {
    // ...
 -1
Author: pyon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-17 16:08:19