Zugriff verweigert auf protected Element
-
Wie meine Vorredner schon erwähnten, hast du den static member "*ptr" nicht initialisiert. Zusätzlich ist das mit dem Zeiger eine ganz gefährliche Sache, da er komplett auf a zeigt. Probiere es mal so:
#include <iostream> class a { protected: a *ptr; virtual void exec() { std::cerr << "message from a" << std::endl;} public: a() { ptr = this; } void func(); }; void a::func() { ptr->exec(); } class b : public a { protected: void exec() { std::cerr << "message from b" << std::endl;} public: void func(); }; void b::func() { a::exec(); exec(); } int main(int argc, char* argv[]) { b my_obj; my_obj.func(); system("Pause"); return 0; }
-
satanfreze schrieb:
Wie meine Vorredner schon erwähnten, hast du den static member "*ptr" nicht initialisiert. ...
schreibst du doch selbst
=>satanfreze schrieb:
... class a { ... a() { ptr = this; } ... }; ... int main(int argc, char* argv[]) { b my_obj; // -> b::b() -> a::a() => a::ptr ist initialisiert ...
Gefährlich wäre natürlich der Zugriff auf das statische a::ptr von außerhalb ... aber dagegen will sich pro_develop vermutlich dadurch absichern, dass er es protected macht.
Schwieriger finde ich da ja (neben der fehlenden Multithreadingfähigkeit), dass bei diesem Design einem konkreten B-Objekt "unter der Hand" ein anderes untergeschoben wird:
int main() { b b1; // b1::a::ptr verweist auf b1::a b b2; // b1::a::ptr verweist auf b2::a !!
Aber es kann sein, dass die o.g. "protected-Besonderheit" genau dagegen schützen will...
Gruß,
Simon2.
-
Danke für die vielen Antworten
Beim Tippen des vereinfachten Beispiels ist mir wohl der statische pointer durch die Lappen gegangen, deshalb hier noch einmal mein Codebeispiel.
@hustbear: Ich habe nun die exec() funktion in b rausgenommen, so greife ich über den Zeiger auf a auf die Funktion in der Basisklasse zu. Das Problem bleibt das selbe.
@Dweb: ich finde die Schreibweise aus C mit Konstruktor(void) besser ...
@Simon2: ich benötige dieses Design, um eine C/C++ Adaption auf eine Library zu realisieren, daher soll das ganze auch diese Form haben ...
Dein erster Ansatz finde ich ganz gut ... aber ich möchte doch auf exec() in a zugreifen, wo doch auch der static pointer drin ist ????????#include "stdafx.h" #include <iostream> using namespace std; class a { protected: static a *ptr; virtual void exec(void) {cerr << "message from a" << endl;} public: a(void) {ptr = this;} static void func(void); }; a *a::ptr = NULL; void a::func(void) { ptr->exec(); } class b : public a { protected: //void exec(void) {cerr << "message from b" << endl;} public: static void func(void); }; void b::func(void) { ptr->exec(); // error C2248: 'a::exec': Kein Zugriff auf protected Element, dessen Deklaration in der Klasse "a" erfolgte } int main(int argc, _TCHAR* argv[]) { return 0; }
-
pro_develop schrieb:
aber ich möchte doch auf exec() in a zugreifen, wo doch auch der static pointer drin ist ?
Simon2 schrieb:
Diese Besonderheit von protected ist mir auch erst ziemlich spät aufgefallen: Man darf nur auf das "eigene a" zugreifen. Das ist aber über den statischen Zeiger ptr nicht mehr gewährleistet.
hustbaer schrieb:
Wenn du sicher weisst dass "ptr" ein "b" ist, dann kannst du den Fehler mit einem static_cast umgehen.
void b::func(void) { static_cast<b*>(ptr)->exec(); // aber nur, wenn "ptr" wirklich auf ein "b"-Objekt zeigt. }
-
tut mir leid ... ich hab's noch nicht kappiert
wenn ich den ptr auf a mit dem this-zeiger auf b initialisiere, dann zeigt
dieser doch auf das Basis-Objekt (Teil a) des b-Objekts ... dann sollte es doch möglich sein, eine Member-Funktion von a aufzurufen ....
-
Du darfst nur direkt mit einem Objekt von B auf die protected-Teile von A zugreifen. Jedoch nicht mit einem Objekt von A oder Zeiger auf A.
class Base { protected: int test; }; class Derived : public Base { void func(); }; void Derived::func() { Base* ptr = new Base(); cout << ptr->test; // Nicht erlaubt cout << test; // Ist erlaubt, entspricht ja ( this->test ) }
Die abgeleitete Klasse hat keinen Sonderzugriff auf protected Elemente von Base. Sie darf nur über ein Objekt von sich selbst drauf zu greifen.
Verstanden
?
Lg freeG
-
Hab dir mal ein kleines Beispiel gemacht:
class A { protected: int i; }; class B : public A { public: void fkt() { A a_objekt; B b_objekt; A* ptr; /* Fehler: Innerhalb der "Klasse B" darfst du nur von einem "B-Objekt" aus auf die protected-Teile von A zugreifen. Wenn der Zeiger aber auf ein "A-Objekt" verweist, ist es ein Zugriff von außerhalb, und das erlaubt protected nicht. */ ptr = &a_objekt; // Dieses Objekt hat nichts mit der "Klasse B" zu tun... ptr->i; // ...und du befindest dich außerhalb von "Klasse A" --> Fehler /* "b_objekt" beinhaltet einen "A-Teil". ( Es wird ja der Konstruktor der "Klasse A" aufgerufen, wenn du ein "B-Objekt erstellst. ) */ ptr = &b_objekt; // Es ist ein "B-Objekt"... ptr->i; // ...Du bist innerhalb der "Klasse B" --> Zugriff erlaubt } }; int main() { return 0; }
-
Danke für eure Hilfe
Danke fr33g, mit deiner Erklärung hab ich's jetzt kappiert
ich hab auch noch einen anderen Test gemacht:
a hugo; a *ptr = &hugo; ptr->exec();
damit taucht genau das gleiche Problem auf ...
Wow ... ich hätte nicht gedacht, dass der Zugriffsschutz so komplex ist ...
damit kann man sich ja regelrecht aussperrendas bedeutet also, dass einzelne Objekte einer Klasse auch gegenseitig vor Zugriffen auf die zugehörigen private oder protected Member geschützt sind ...
-
pro_develop schrieb:
das bedeutet also, dass einzelne Objekte einer Klasse auch gegenseitig vor Zugriffen auf die zugehörigen private oder protected Member geschützt sind ...
Nein.
class foo { public: void bar (foo& other) { other.n = 5; //geht } private: int n; };
Die privaten Member von
other
können von einem anderen Objekt des gleichen Types verändert werden!So habe ich deine Aussage auf jeden Fall verstanden.
-
pro_develop schrieb:
Wow ... ich hätte nicht gedacht, dass der Zugriffsschutz so komplex ist ...
damit kann man sich ja regelrecht aussperrenOhne diese "Komplexität" könnte man
protected
sofort aushebeln, der "Schutz" wäre nicht-existent:// base.cpp class base { protected: int m_i; }; // schummler.cpp class schummel_helper : public base { public: static void set_m_i(base& b, new_i_value) { b.m_i = new_i_value; // wäre schlecht wenn das erlaubt wäre... } }; void schummeln(base& b, int new_i_value) { // man könnte so b.m_i setzen, obwohl dies eine freie funktion ist, die vererbungsmässig so überhaupt gar nix mit "base" zu tun hat schummel_helper::set_m_i(b, new_i_value); }
-
hustbaer schrieb:
Ohne diese "Komplexität" könnte man
protected
sofort aushebeln, der "Schutz" wäre nicht-existentDiese Sonderregel hat aber auch Nachteile, welche einen zu teilweise nicht sehr sauberen Workarounds zwingt.
Siehe z.B. in einem älteren Thread von mir (gerade am Anfang).
-
@Nexus: ich denke besser so als anders rum.
-
Es schadet nie, etwas von mehreren Seiten zu betrachten
-
Natürlich nicht.
Manchmal bringt es aber auch nix, weil ein Fall gänzlich klar ist (und auch nach weiterer Betrachtung bleibt)