Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Protected member function address in derived class is not accessible

#include <iostream>

class A {
protected:
    void foo()
    {}
};

class B : public A {
public:
    void bar()
    {
       std::cout << (&A::foo) << std::endl;
    }
};

int main()
{
    B b;
    b.bar();
}

Here I am trying to get address of protected member function of base class. I am getting this error.

main.cpp: In member function ‘void B::bar()’:
main.cpp:5: error: ‘void A::foo()’ is protected
main.cpp:13: error: within this context
make: *** [all] Error 1

Changing foo to public works. Also printing &B::foo works. Can you please explain why we can't get address of protected member function of base class?

like image 785
Ashot Avatar asked Feb 20 '15 06:02

Ashot


People also ask

Is protected is accessible in derived class?

protected members are not accessible in derived classes.

Are protected members of a base class accessed in the derived class when inherited?

If a class is derived privately from a base class, all protected base class members become private members of the derived class. Class A contains one protected data member, an integer i . Because B derives from A , the members of B have access to the protected member of A .

How do I access a protected function from another class?

Create a public function that calls the protected one. This can be accomplished through either deriving Test or creating another class, Test2, and declaring Test a friend of Test2 and having Test2 contain an instance of Test. Seeing all the instructions of your homework would help.

Which non member function can access protected members of a class?

B. Friend function can access protected data members of the class.


2 Answers

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 denote C or a class derived from C. All other accesses involve a (possibly implicit) object expression (5.2.5). In this case, the class of the object expression shall be C or a class derived from C. [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.

like image 136
Praetorian Avatar answered Oct 12 '22 09:10

Praetorian


I was curious and tried the following example:

#include <iostream>
using namespace std;

class A {
public:
    void foo()
    {
    }
};

class B : public A {
public:
    void bar()
    {
       printf("%p\n", (&A::foo));
       printf("%p\n", (&B::foo));
    }
};

int main()
{
    B b;
    b.bar();
}

Actually, I see that &A::foo == &B::foo, so for protected member of base class you can use derived class member to take address. I suppose in case of virtual functions this will not work

like image 29
VolAnd Avatar answered Sep 18 '22 17:09

VolAnd