Frage zu Vererbungsstruktur und proteced
-
Folgender beispielhafter Code:
class Basis { protected: virtual void render() = 0; }; class KindA : public Basis { protected: virtual void render() { //impl ... } }; class KindB : public Basis { protected: virtual void render() { muchRenderObjects[i]->render(); } //Compilefehler private: std::vector<Basis*> muchRenderObjects; };wenn ich in KindB auf Basis-Objekte die Methode render() anwenden will, hab ich keine Rechte auf die protected-Methode zuzugreifen.
Ich dachte, dass geht? In meinem C++ Kompendium habe ich dazu nichts weiter gefunden. Mal schnell in Java probiert: da geht es.Nun wollt ich wissen: ist das standardkonform oder ein Compilerproblem?
Und wenn es standardkonform ist, wie kann man sowas elegant lösen? Mir würde jetzt nur einfallen, dass render public zu machen.MfG Pellaeon
PS: Das muchRenderObjects[i]->render(); ist nur vereinfacht und steht natürlich nicht alleine im Code.
-
Du musst die Klasse schon vererben.
class KindB : public Basis { // ... };
-
sry die erben, habs nur vergessen reinzuschreiben im Bsp Code jetzt isses drinne
-
render in Basis ist doch rein virtuell. Was willst du da aufrufen? Wie hast du diese Basisobjekte überhaupt erstellt?
-
Pellaeon schrieb:
... Nun wollt ich wissen: ist das standardkonform oder ein Compilerproblem? Und wenn es standardkonform ist, wie kann man sowas elegant lösen? Mir würde jetzt nur einfallen, dass render public zu machen. ...
Wenn ich dein Programm richtig interpretiere, dann sind durch
std::vector<Basis*> muchRenderObjects;in der Klasse KindB Zeiger auf verschiedene unabhängige Objekte der Basisklasse definiert.
Auch abgeleitete Klassen haben auf unabhängige Objekte ihrer Basisklassen nur den Zugriff, denn alle anderen haben. D.h. um auf eine Methode zuzugreifen müsste sie auch öffentlich sein.
Es ist schwer zu sagen, was du nun machen könntest, da deine Methode sowieso rein virtuell ist. Normalerweise könnte man das Problem beseitigen indem man die abgeleitete Klasse zum friend der Basisklasse macht.
Gruß
-
Hallo,
also ich hab jetzt erstmal eine friend-Deklaration hineingemacht.
Und da habe ich auch noch eine Frage dazu.
Ich benutzte STL-Algorithmen, welche auch auf das Render zugreifen sollen. Meine Funktionsobjekte besitzen da jetzt natürlich erstmal keine Rechte auf die protected-Methode. Soweit so normal. Nun habe ich folgendes direkt in der Klasse definiert:template<typename T> struct Render : std::unary_function<T,void> { void operator() (T* arg) { arg->render(); } };Also wenn ich auf mein Bsp im ersten Post zurück komme, dann wäre diese Struktur innerhalb der Klasse KindB und Klasse Basis hat eine friend-Deklaration auf KindB.
Instanzen diese Struktur wird dann auch innerhalb von Methoden von KindB genutzt.
Meine Frage: ist das legaler ISO C++ Code? Weil ich hab Compiler die nehmen das ohne Fehler und Warnungen, andere dagegen meckern, dass auf render kein Zugriff gestattet ist.MfG Pellaeon
Edit: also in Quellcode ausgedrückt, sowas:
class Basis { friend class KindB; protected: virtual void render() = 0; }; class KindA : public Basis { protected: virtual void render() { //impl ... } }; class KindB : public Basis { protected: virtual void render() { muchRenderObjects[i]->render(); } //Compilefehler private: std::vector<Basis*> muchRenderObjects; template<typename T> struct Render : std::unary_function<T,void> { void operator() (T* arg) { arg->render(); } }; };
-
*push*
-
*pop*
-
Hallo,
Meine Frage: ist das legaler ISO C++ Code? Weil ich hab Compiler die nehmen das ohne Fehler und Warnungen, andere dagegen meckern, dass auf render kein Zugriff gestattet ist.
Für mich ist das standardkonformer Code... (ausser, dass das i in der render-Definition der KindB-Klasse undefiniert ist, aber die Schleife habe ich mir dazu gedacht ;))
MfG,
Probe-Nutzer
-
[unsinn]...[/unsinn]
Edit: jo sieht korrekt aus.

-
Folgende Antwort habe woanders bekommen:
Danny schrieb:
Let's simplify the question. Essentially, you want to know whether an embedded class can access non-public members of its enclosing class (either inherited or defined in the enclosing class itself). The answer is no. An embedded class is like any other class. It can only access public members of its enclosing class, unless it's a friend.
Nach dieser Erklärung wäre mein Code also falsch und der Compiler macht es nicht richtig.
-
Pellaeon schrieb:
wenn ich in KindB auf Basis-Objekte die Methode render() anwenden will, hab ich keine Rechte auf die protected-Methode zuzugreifen.
Ich dachte, dass geht?protected erlaubt den Zugriff auf Elemente von Basisklassensubobjekten von Objekten der abgeleiteten Klasse, nicht auf beliebige Objekte der Basisklasse. Um diese sicherzustellen, muss der Objektparameter vom Typ der abgeleiteten Klasse sein (wenn wir auf nicht-statische Elemente zugreifen sollen). Also
struct Base { protected: void foo(); }; struct Derived2 : Base {}; struct Derived2 : Base { void bar(Base* p) { foo(); // ok, implizit in this->foo() umgewandelt Base::foo(); // ok, dito this->foo(); // ok this->Base::foo(); // ok ... ((Base*)this)->foo(); // Fehler p->foo(); // Fehler, könnte ja z.B. eine Basis von Derived1 sein, Derived2 hat dort nichts zu suchen } };in
muchRenderObjects[i]->render();ist der Typ des Objektparameters Basis und nicht KindB - es gibt keine Garantie, dass diese Zeiger auf Subobjekte von KindB-Objekten zeigen, also ist dies nicht erlaubt.
Mit der verschachtelten Klasse klappt es auch nicht. Eine verschachtelte Klasse hat keine besonderen Zugriffsrechte auf die umliegende Klasse und friendship ist nicht transitiv; das friend class KindB; wirkt sich nur auf Definitionen für Member der Klasse KindB aus, nicht auf Member von Membern (also die Member der verschachtelten Klasse).
Die Frage, ob verschachtelte Klassen Zugriff auf Member der umschließenden Klasse haben, ist relativ alt, und wurde lange nicht ganz einheitlich behandelt. Aus diesem Grunde gibt es noch einige Compiler, die hier mehr Zugriff gewähren, als eigentlich zulässig ist, nicht zuletzt aus Kompatibilitätsgründen mit existierendem Code.