Im einführenden Beispiel des vorigen Abschnitts wurde Laster von Auto public abgeleitet, denn die Definition von Laster begann folgendermaßen:
//... class Laster: public Auto { //...
Im Gegensatz dazu könnte man auch protected ableiten, also so:
//... class Laster: protected Auto { //...oder auch private:
//... class Laster: private Auto { //...
Worin unterscheiden sich diese Varianten?
Sowohl bei einer public-Ableitung, protected-Ableitung, als auch einer private-Ableitung erbt die ableitende Klasse (hier: Laster) alle Elemente der Basisklasse, und kann -je nach deren Deklaration als private:, protected: oder public: in der Basisklasse- darauf zugreifen. Insoweit besteht kein Unterschied zwischen den Varianten.
Ein Unterschied kommt erst dann zum Vorschein, wenn Anwender der abgeleiteten Klasse (Laster) versuchen, auf Auto-Elemente zu zugreifen:
Bei einer public geerbten Schnittstelle bleibt also für weiter davon abgeleitete Klassen die gesamte public- und protected-Schnittstelle der Basisklasse erhalten.
(In jedem Fall sind in den abgeleiteten Klassen aber alle Elemente der Basisklassen enthalten, auch wenn nur beschränkt darauf zugegriffen werden kann. Eine Klasse kann also durch Ableiten nicht schrumpfen, sondern nur erweitert werden.)
In den meisten Fällen wird man public ableiten. Allerdings kann es sein, daß eine neue Klasse zwar eine Basisklasse sinnvoll intern verwenden kann, aber zu seinem Anwender wiederum eine derart stark geänderte Schnittstelle hat, daß ein Durchgriff auf die Basisklasse nicht mehr sinnvoll ist. Dann wird man private ableiten. (Man sollte sich dann allerdings die Frage stellen, ob wirklich noch eine ,,IST EIN``-Beziehung zwischen den Klassen plausibel ist, oder nicht eher eine ,,HAT EIN``-Beziehung; im letzteren Fall sollte man gar nicht ableiten, sondern statt dessen ein Element vom Typ der zugrunde liegenden Klasse einfügen.)
Wenn man den Durchgriff auf einzelne Elemente dennoch ermöglichen möchte, dann kann man das mit einer Deklaration in der abgeleiteten Klasse etwa in der Art tun:
//... class Laster: private Auto { public: Auto::getRaeder; /...
Angenommen, man hat eine kleine Klasse A mit einem public-, einem protected- und einem private-Teil, dann kann eine Methode der Klasse auf alle Elemente zugreifen:
class A { private: int privA; protected: int protA; public: int publA; virtual void methode( int wert ) { privA = wert; // ok protA = wert; // ok publA = wert; // ok } };
Davon werden drei Klassen (BprivA, BprotA, BpublA) abgeleitet, je eine private, eine protected und eine public; sowie von diesen dreien wieder je eine CpubB... (und zwar public). In den dabei enthaltenen Methoden sind die unzulässigen Zugriffe auskommentiert:
// von A private erben: class BprivA: private A { public: virtual void methode( int wert ) { //privA = wert; // geht nicht, weil private protA = wert; // ok publA = wert; // ok } }; class CpublBprivA: public BprivA { public: virtual void methode( int wert ) { //privA = wert; // geht nicht, weil private //protA = wert; // geht nicht, weil private von A geerbt //publA = wert; // geht nicht, weil private von A geerbt } }; // von A protected erben: class BprotA: protected A { public: virtual void methode( int wert ) { //privA = wert; // geht nicht, weil private protA = wert; // ok publA = wert; // ok } }; class CpublBprotA: public BprotA { public: virtual void methode( int wert ) { //privA = wert; // geht nicht, weil private protA = wert; // ok publA = wert; // ok } }; // von A public erben: class BpublA: public A { public: virtual void methode( int wert ) { //privA = wert; // geht nicht, weil private protA = wert; // ok publA = wert; // ok } }; class CpublBpublA: public BpublA { public: virtual void methode( int wert ) { //privA = wert; // geht nicht, weil private protA = wert; // ok publA = wert; // ok } };
Die Zugriffsmöglichkeiten über Objekte der einzelnen Klassen sieht man hier (unzulässige Zugriffe sind wieder auskommentiert):
int main( int nargs, char **args ) { A einA; //einA.privA = 12;, // geht nicht, weil private //einA.protA = 12;, // geht nicht, weil protected einA.publA = 12; // ok BprivA einBprivA; //einBprivA.privA = 12; // g.n., w. priv. && priv. von A geerbt //einBprivA.protA = 12; // g.n., w. prot. && priv. von A geerbt //einBprivA.publA = 12; // g.n., w. priv. von A geerbt CpublBprivA einCpublBprivA; //einCpublBprivA.privA = 12; // g.n., w. priv. && priv. von A geerbt //einCpublBprivA.protA = 12; // g.n., w. prot. && priv. von A geerbt //einCpublBprivA.publA = 12; // g.n., w. priv. von A geerbt BprotA einBprotA; //einBprotA.privA = 12; // g.n., w. priv. && prot. von A geerbt //einBprotA.protA = 12; // g.n., w. prot. && prot. von A geerbt //einBprotA.publA = 12; // g.n., w. prot. von A geerbt CpublBprotA einCpublBprotA; //einCpublBprotA.privA = 12; // g.n., w. priv. && prot. von A geerbt //einCpublBprotA.protA = 12; // g.n., w. prot. && prot. von A geerbt //einCpublBprotA.publA = 12; // g.n., w. prot. von A geerbt BpublA einBpublA; //einBpublA.privA = 12; // geht nicht, weil private //einBpublA.protA = 12; // geht nicht, weil protected einBpublA.publA = 12; // ok CpublBpublA einCpublBpublA; //einCpublBpublA.privA = 12; // g.n., weil private //einCpublBpublA.protA = 12; // g.n., weil protected einCpublBpublA.publA = 12; // ok }
Die wesentlichen Zugriffsmöglichkeiten lassen sich auch in einer
Tabelle darstellen. Dabei wird wieder von der obigen Klasse A
ausgegangen:
Zugriff auf | privA | protA | publA |
über: | |||
Methode in A: | ja | ja | ja |
Objekt vom Typ A: | nein | nein | ja |
Falls B: private A abgeleitet und C: public B | |||
Methode in B: | nein | ja | ja |
Objekt vom Typ B: | nein | nein | nein |
Methode in C: | nein | nein | nein |
Objekt vom Typ C: | nein | nein | nein |
Falls B: protected A abgeleitet und C: public B | |||
Methode in B: | nein | ja | ja |
Objekt vom Typ B: | nein | nein | nein |
Methode in C: | nein | ja | ja |
Objekt vom Typ C: | nein | nein | nein |
Falls B: public A abgeleitet und C: public B | |||
Methode in B: | nein | ja | ja |
Objekt vom Typ B: | nein | nein | ja |
Methode in C: | nein | ja | ja |
Objekt vom Typ C: | nein | nein | ja |
AnyWare@Wachtler.de