The following simple piece of code, 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)
is turned on in VC, but it doesn't give any warning.
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 shouldn't pass an object of type myclass
? It doesn't matter actually, g++ gives the same error but VC compiles the code without any 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();
}
This is correct. The relevant part of the Standard has been quoted above, but here's the rationale for what it's worth.
The semantics of protected
in C++ means "this member can be accessed from methods of this class or any derived classes, but only when dynamic type of object being accessed is guaranteed to be the same as, or derived from, the type of *this
".
The latter bit may not quite be obvious, so 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
could have its own opinion on how its protected members should be handled (what are the invariants, etc), and it should be strictly between it and its base class (and its derived classes, but only if it decides to not hide that field by making it private
). Cross-hierarchy access is contrary to this model, since it would effectively mean that the base class decides for the entire hierarchy in advance; for very abstract classes on top of deep hierarchies, this can be undesirable.
Now back to your specific problem - it should be fairly obvious by now. Once you obtain a member function pointer, you may call the function pointed to by that pointer with any receiver of a matching type. For a protected method of a base class, this means that, if you could obtain a pointer to it typed to the base class (rather than your own class), you could then call it, passing it a pointer to a type different from your class (or derived from it), violating the rules for protected access outlined above. Therefore, you are not permitted to do this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With