Is this standard C ++ code?

The following simple code snippet compiles with VC2008, but g ++ rejects the code:

#include <iostream> class myclass { protected: void print() { std::cout << "myclass::print();"; } }; struct access : private myclass { static void access_print(myclass& object) { // g++ and Comeau reject this line but not VC++ void (myclass::*function) () = &myclass::print; (object.*function)(); } }; int main() { myclass object; access::access_print(object); } 

(/W4) included in VC, but it does not give any warnings.

g ++ 4.4.1 gives me an error:

 correct.cpp: In static member function 'static void access::access_print(myclass&)': correct.cpp:6: error: 'void myclass::print()' is protected 

If g ++ is correct, how do I access a protected member of a class? Is there another way?


@Suroot Do you mean that I should not pass an object like myclass ? It doesn't really matter, g ++ gives the same error, but VC compiles the code without warning.

 #include <iostream> class myclass { protected: void print() { std::cout << "myclass::print();"; } }; struct access : private myclass { static void access_print() { myclass object; void (myclass::*function) () = &myclass::print; (object.*function)(); } }; int main() { access::access_print(); } 
+4
source share
3 answers

I believe g ++ and goau are correct. The qualifier for the protected member must be of type "access" or received, so I believe in the code:

 void (myclass::*function) () = &access::print; 

will compile.

I believe this is due to 11.5.1:

... If access [ed. to a protected member] must form a pointer to a member, the naming specifier must name the derived class (or any class derived from this class).

+6
source

It is right. The relevant part of the Standard is given above, but here is the rationale for what it costs.

The protected semantics in C ++ means that "this element can be accessed from the methods of this class or any derived classes, but only when the dynamic type of the object being accessed is guaranteed to be the same as or obtained from type *this ".

The last bit may not be quite obvious, here is an example:

  class Base { protected: int X; }; class Derived : public Base { void Foo(Base* b, Derived* d) { this->X = 123; // okay - `this` is definitely either Derived // or inherited from Derived d->X = 456; // also okay, for the same reason b->X = 789; // NOT OKAY; b could point to instance of some other class // Derived2, which isn't inherited from Derived! } }; 

This is by design - the idea is that Derived2 can have its own opinion on how its protected members should be handled (what are the invariants, etc.), and this should be strictly between him and his base class (and its derivatives classes, but only if he decided not to hide this field by making it private ). Access to the cross hierarchy contradicts this model, since it actually means that the base class pre-decides the entire hierarchy; for very abstract classes on top of deep hierarchies this may not be desirable.

Now back to your specific problem - by now this should be pretty obvious. Once you get a pointer to a member function, you can call the function that this pointer points to with any recipient of the appropriate type. For a protected method of a base class, this means that if you could get a pointer to it that would be introduced into the base class (and not to your own class), you could call it by passing it a pointer to a type other than your class (or derived from it) in violation of the secure access rules described above. Therefore, you are not allowed to do this.

+13
source

Since the object is passed as a parameter, you cannot directly access private / protected functions.

Edit: Changed the myclass class for an object

+2
source

All Articles