Question

En C ++, je ne peux pas penser à un cas où je voudrais hériter privé / protégé d'un classe de base:

class Base;
class Derived1 : private Base;
class Derived2 : protected Base;

Est-il vraiment utile?

Était-ce utile?

La solution

Il est utile lorsque vous voulez avoir accès à certains membres de la classe de base, mais sans les exposer dans votre interface de classe. l'héritage privé peut également être considérée comme une sorte de composition: C ++ faq-lite donne l'exemple suivant pour illustrer cette déclaration

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
};

Pour obtenir la même sémantique, vous pouvez aussi écrire la classe de voiture comme suit:

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
}; 

Cependant, cette façon de faire présente plusieurs inconvénients:

  • votre intention est beaucoup moins claire
  • il peut conduire à l'héritage multiple abusif
  • il rompt l'encapsulation de la classe du moteur puisque vous pouvez accéder à ses membres protégés
  • vous êtes autorisé à remplacer les méthodes virtuelles moteur, ce qui est quelque chose que vous ne voulez pas si votre objectif est une composition simple

Autres conseils

privé peut être utile dans un certain nombre des circonstances. Juste un d'entre eux sont politiques:

est la spécialisation de modèle de classe partielle la réponse à ce problème de conception? .

Une autre occasion où il est utile est d'interdire la copie et l'attribution:

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

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

Parce que nous ne voulons pas que l'utilisateur dispose d'un pointeur de type noncopyable* à notre objet, nous dérivons en privé. Qui compte non seulement pour noncopyable, mais beaucoup d'autres ces classes trop (politiques étant les plus courants).

modèles d'héritage public IS-A.
modèles d'héritage non-public est-IN-MIS EN ŒUVRE termes de.
modèles de confinement HAS-A, ce qui équivaut à IS-EN MIS EN ŒUVRE termes de.

Sutter sur le sujet . Il explique quand vous choisiriez l'héritage non-public sur le confinement pour les détails de mise en œuvre.

Par exemple, lorsque vous souhaitez réutiliser la mise en œuvre, mais pas l'interface d'une classe et passer outre ses fonctions virtuelles.

héritage privé est surtout utilisé pour une mauvaise raison. Les gens l'utilisent pour IS-EN-MIS EN OEUVRE-termes de, comme il est indiqué dans une réponse précédente, mais dans mon expérience, il est toujours plus propre de conserver une copie plutôt que d'hériter de la classe. Une autre réponse plus tôt, celui sur CBigArray, fournit un parfait exemple de cet anti-modèle.

Je me rends compte qu'il peut y avoir des cas où a-un ne fonctionne pas en raison de trop zélés usage de « protégé », mais il est préférable de fixer la classe brisée que de briser une nouvelle classe.

Je l'ai utilisé aussi bien inheritence privé et protégé à un moment ou un autre.

inheritence privé est utile lorsque vous voulez quelque chose d'avoir le comportement de la classe de base, et être en mesure de passer outre cette fonctionnalité, mais vous ne voulez pas que le monde entier soit au courant et l'utiliser. Vous pouvez toujours utiliser l'interface d'une classe privée dérivée en ayant une fonction de retour cette interface. Il est également utile lorsque vous pouvez avoir des choses se faire enregistrer pour écouter les callbacks car ils peuvent s'inscrire à l'aide de l'interface privée.

Protégé inheritence est particulièrement utile lorsque vous avez une classe de base qui dérive des fonctionnalités utiles d'une autre classe, mais vous ne souhaitez que ses classes dérivées pour pouvoir l'utiliser.

Une fois, je mis en œuvre ces structures de données sous forme de classes:

  • Liste de liens
  • array générique (résumé)
  • Tableau simple (tableau générique hérite de)
  • array Big (hérite de tableau générique)

La grande interface de tableau ferait ressembler à un tableau, cependant, il était en fait une liste chaînée de simples tableaux de taille fixe. Donc, je déclarai comme ceci:

template <typename T>
class CBigArray : public IArray, private CLnkList {
    // ...
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top