protected
-
class B; B* temp; class A { protected: int x; }; class B: public A { protected: int y; }; class C: public B { public: void foo() { x = 7; y = 8; temp->y = 2; // geht nicht } };
Wieso geht das nicht? protected Member sollten doch in abgeleiteten Klassen verfügbar sein.
-
temp ist doch eine Referenz auf ein B-Objekt. Du kannst auf geerbte Protected Variablen nur zugreifen, wenn Sie auch in der selben Instanz sind (also in this).
-
Sonst ist doch der Zugriff auch immer auf Klassenebene.
-
Aber, mit private ist die Situation anderes!!!
class B; B* temp; class A { protected: int x; }; class B: public A { int r; protected: int y; void s () { temp->r = 3; // geht ok!!! } }; class C: public B { public: void foo() { x = 7; y = 8; temp->y = 2; // geht nicht } };
-
itman schrieb:
Aber, mit private ist die Situation anderes!!!
class A { protected: int x; }; class B: public A { int r; protected: int y; void s () { temp->r = 3; // geht ok!!! } }; class C: public B { public: void foo() { x = 7; y = 8; temp->y = 2; // geht nicht } };
Du hast da jetzt was falsch verstanden
Der Ausdruck temp->r = 3 steht doch in B::s. Also in der gleichen Klasse wie r.
-
Bei protected gibt es eine Sonderregel: Der Zugriff von einer Memberfunktion der Klasse D auf ein Element der Basisklasse B kann nicht über ein Objekt (oder Pointer oder Referenz) der Klasse B geschehen, sondern nur über ein Objekt der Klasse D (oder von D abgeleiteter Klassen.)
-
Der Ausdruck temp->r = 3 steht doch in B::s. Also in der gleichen Klasse wie r.
Natuerlich, aber private variablen koennen im anderen (und auch in vererbenden Klassen) Klassen nicht zugrifft werden.
-
Jetzt hab ich aber ein Problem, ich muss ne protected Methode der Basisklasse aufrufen. Die Basisklasse ist abstrakt, die Methode soll nicht public sein, deshalb protected.
Von der Basisklasse leiten mehrere Klassen ab, deshalb ist der Zeiger vom Typ Basisklasse*.Ich hab mir mal schnell ein Beispiel ausgedacht:
class Objekt { protected: void die() {} }; class Haus: public Objekt {}; class Rakete: public Objekt { public: void kill(Objekt* target) { target->die(); // geht nicht } };
Wie löst man sowas am besten? Ich will doch, dass die Rakete alle Objekte zerstören kann, nicht nur andere Raketen.
-
z.B:
[cpp]
class Objekt
{
protected:
void die() {}
};class Haus: public Objekt {};
class Rakete: public Objekt
{
private:
void dieWrapper (){die();}
public:
void kill(Objekt* target)
{
target->dieWrapper(); // geht nicht
}
};
-
IMHO ist das ein Mißbrauch von Vererbung. Du leitest Haus und Rakete von Objekt ab, nur weil sie sich gegenseitig zerstören können sollen (protected die-Funktion.) Das ist aber kein gutes Motiv für Vererbung. Eher gehören verschiedene Waffen (können zerstören) zusammen und verschiedene Ziele (können zerstört werden) zusammen. Dass dann nicht jeder ein Haus zerstören kann, mußt du durch deine Programmlogik sicherstellen, nicht durch das Typsystem.
-
Bashar schrieb:
IMHO ist das ein Mißbrauch von Vererbung. Du leitest Haus und Rakete von Objekt ab, nur weil sie sich gegenseitig zerstören können sollen (protected die-Funktion.) Das ist aber kein gutes Motiv für Vererbung. Eher gehören verschiedene Waffen (können zerstören) zusammen und verschiedene Ziele (können zerstört werden) zusammen. Dass dann nicht jeder ein Haus zerstören kann, mußt du durch deine Programmlogik sicherstellen, nicht durch das Typsystem.
Nein ich leite nicht aus diesem Grund ab. Sondern weil Haus und Rakete gemeinsame Eigenschaften haben, die alle Objekte haben, z.B. Position oder eben eine die()-Methode.
Das ist jetzt wirklich ein frei erfundenes Beispiel, glaub mir, ich weiss, wann ich Vererbung einsetzen sollte.
In Wirklichkeit würde ich noch viel genauer Unterscheiden, z.B. Haus von Gebäude ableiten, Gebäude von Objekt oder Rakete->Geschoss->BeweglichesObjekt->Objekt, usw.Aber alle Objekte müssen zerstörbar sein, deshalb die die() Funktion in Objekt. Public würde schon gehen, aber dann kann man (theoretisch) so zum Spaß in irgendeinem völlig anderen Kontext mal ein paar Objekte sinnlos zerstören. Objekte sollen aber nur aufgrund von Interaktion mit anderen Objekten sterben können, deshalb nicht public.
Wäre friend eine Designtechnisch annehmbare Lösung?
-
Ich würde eindeutig public vorziehen. Wenn ein Hamster deine Cruise Missile zerstört, ist es ein Fehler in der Programmlogik. IMHO kann sowas nicht durch die Zugriffsebenen regeln; die benutzt man, um unwichtige Implementationsdetails zu verstecken und damit die Abhängigkeiten zwischen Klassen zu regeln.
-
Ok, aber ich muss auch Datenelemente von anderen Objekten abfragen und ich habe eigentlich nicht vor, für jedes Ding nen public getter zu schreiben. Vor allem weil es ja auch eigentlich keine public getter dafür geben soll, ich will ja gar nicht, dass man das von außen abfragen kann.
Um das Beispiel zu erweitern:
class Rakete: public Objekt { public: void attack(Objekt* target) { if (!target->unverwundbar && !canBeTargeted && ...) // geht nicht target->die(); // geht nicht } };
-
Es gibt ein OO-Prinzip: "Tell, don't ask". Es geht die Rakete nichts an, ob das Ziel unverwundbar ist oder sonstwas:
void attack(Objekt *target) { target->damage(100); // Beispiel }
Das Haus weiß selbst, wann es "fertig" ist. Zu canBeTargeted: Das sieht sehr nach einer öffentlichen Eigenschaft aus ... warum willst du nicht, dass das abfragbar ist? Ich versteh ehrlich gesagt nicht, was du für eine Abneigung gegen public (Memberfunktionen!) hast.
-
k, danke mal.