Frage

In C ++ kann ich denke nicht, von einem Fall, in dem ich von einem privaten / geschützt erben möge Basisklasse:

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

Ist es wirklich sinnvoll?

War es hilfreich?

Lösung

Es ist nützlich, wenn Sie den Zugriff auf einige Mitglieder der Basisklasse haben wollen, aber ohne sie in Ihrer Klasse Schnittstelle auszusetzen. Private Vererbung kann auch als eine Art Komposition zu sehen: die C ++ FAQ-lite gibt folgendes Beispiel diese Aussage zu illustrieren

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

das gleiche semantische zu erhalten, könnten Sie auch das Auto-Klasse wie folgt schreiben:

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

Allerdings ist diese Art und Weise mehrere Nachteile zu tun hat:

  • Ihre Absicht ist viel weniger klar
  • kann es zu missbräuchlicher Mehrfachvererbung führt
  • es bricht die Kapselung der Motorklasse, da Sie seine geschützte Member zugreifen können
  • Sie sind Motor virtuelle Methoden außer Kraft setzen darf, das ist etwas, was Sie nicht wollen, wenn Ihr Ziel ist eine einfache Zusammensetzung
  • ist

Andere Tipps

Privat kann in ganz wenigen Fällen nützlich sein. Nur einer von ihnen Richtlinien:

Ist partielle Klasse Template-Spezialisierung die Antwort auf dieses Design-Problem? .

Eine weitere Gelegenheit, wo es sinnvoll ist, ist das Kopieren zu verbieten und die Zuordnung:

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

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

Weil wir nicht wollen, dass der Benutzer einen Zeiger vom Typ noncopyable* zu unserem Objekt hat, leiten wir privat. Das gilt nicht nur für noncopyable, sondern auch viele andere solche Klassen zu (Politik ist die gebräuchlichste Form).

öffentliche Vererbung Modelle IST-A.
Nicht-öffentliche Vererbung Modelle IS-implemented-IN-Terms-of.
Contain Modelle HAS-A, die IS-implemented-IN-Terms-of entspricht.

Sutter zum Thema . Er erklärt, wenn Sie nicht-öffentliche Vererbung über Containment für Implementierungsdetails wählen würden.

Zum Beispiel, wenn Sie die Implementierung wiederverwenden, aber nicht die Schnittstelle einer Klasse und ihre virtuellen Funktionen außer Kraft setzen.

Privat Erbe ist vor allem für falschen Grund verwendet. Die Leute benutzen es IS-implemented-IN-Terms-of, in einer früheren Antwort, wie angegeben, sondern eine Kopie meiner Erfahrung nach eher ist es immer mehr sauber zu halten, als von der Klasse erben. Eine weitere frühere Antwort, die man über CBigArray, stellt ein perfektes Beispiel für dieses anti-Muster.

Ich weiß, dass es Fälle geben kann, wenn hat-ein nicht aufgrund übereifriger funktioniert Verwendung von „geschützt“, aber es ist besser, die gebrochene Klasse zu beheben, als eine neue Klasse zu brechen.

Ich habe sowohl private und geschützte inheritence an einem Punkt oder einem anderen verwendet.

Privat inheritence ist nützlich, wenn Sie etwas wollen, das Verhalten der Basisklasse haben, und dann in der Lage sein, diese Funktionalität außer Kraft zu setzen, aber Sie wollen nicht die ganze Welt bewusst zu sein und zu nutzen. Sie können immer noch die Schnittstelle einer privat abgeleiteten Klasse verwenden, indem Sie eine Funktion, die eine Schnittstelle zurückkehren zu müssen. Es ist auch nützlich, wenn Sie können die Dinge sich haben registrieren Sie sich für Rückrufe zu hören, wie sie sich registrieren, können die private Schnittstelle.

Geschützte inheritence ist besonders nützlich, wenn Sie eine Basisklasse haben, die von einer anderen Klasse nützliche Funktionalität leitet sich aber Sie wollen nur ihre abgeleiteten Klassen der Lage sein, es zu benutzen.

I umgesetzt einmal diese Datenstrukturen als Klassen:

  • verlinkte Liste
  • Allg Array (Zusammenfassung)
  • Einfache Array (erbt von generischer Array)
  • Big-Array (erbt von generischer Array)

Die Schnittstelle des großen Array wäre es wie ein Array aussehen, aber es war eigentlich eine verknüpfte Liste von fester Größe einfacher Arrays. So erklärte ich es wie folgt aus:

template <typename T>
class CBigArray : public IArray, private CLnkList {
    // ...
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top