#include
class A {
protected:
void foo()
{}
};
class B : public A {
public:
void bar()
{
std::cout << (&A::foo) &
B is allowed to access protected members of A as long as the access is performed through an object of type B. In your example you're trying to access foo through A, and in that context it is irrelevant whether B derives from A or not.
From N3337, §11.4/1 [class.protected]
An additional access check beyond those described earlier in Clause 11 is applied when a non-static data member or non-static member function is a protected member of its naming class (11.2) As described earlier, access to a protected member is granted because the reference occurs in a friend or member of some class
C. If the access is to form a pointer to member (5.3.1), the nested-name-specifier shall denoteCor a class derived fromC. All other accesses involve a (possibly implicit) object expression (5.2.5). In this case, the class of the object expression shall beCor a class derived fromC. [Example:class B { protected: int i; static int j; }; class D1 : public B { }; class D2 : public B { friend void fr(B*,D1*,D2*); void mem(B*,D1*); }; // ... void D2::mem(B* pb, D1* p1) { // ... int B::* pmi_B = &B::i; // ill-formed int B::* pmi_B2 = &D2::i; // OK // ... } // ...—end example]
Your example is very similar to the code in D2::mem, which shows that trying to form a pointer to a protected member through B instead of D2 is ill-formed.