无法访问派生类中受保护的成员函数地址

时间:2015-02-20 06:34:42

标签: c++ inheritance protected member-function-pointers

#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();
}

这里我试图获取基类的受保护成员函数的地址。我收到了这个错误。

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

将foo改为公共工程。打印&B::foo也有效。能否解释为什么我们无法得到基类的受保护成员函数的地址?

3 个答案:

答案 0 :(得分:6)

只要通过B类型的对象执行访问,就允许

A访问B的受保护成员。在您的示例中,您尝试通过foo访问A,并且在该上下文中B是否来自A无关紧要。

来自N3337,§11.4/ 1 [class.protected]

  

当非静态数据成员或非静态成员函数是其命名类的受保护成员时,将应用超出第11章中所述之外的其他访问检查(11.2)如上所述   之前,授予对受保护成员的访问权限,因为该引用发生在某个类C的朋友或成员中。如果访问要形成指向成员的指针(5.3.1),则嵌套名称说明符应表示C或   来自C 的类。所有其他访问都涉及(可能是隐式的)对象表达式(5.2.5)。在这种情况下,对象表达式的类应为C或从C派生的类。 [示例:

 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
   // ...
 }
 // ...
     

- 示例]

您的示例与D2::mem中的代码非常相似,后者表明尝试通过B而不是D2形成指向受保护成员的指针是不正确的。

答案 1 :(得分:1)

似乎我找到了答案。如果我们可以获得成员函数的指针,我们可以为其他类型A(不是this)的对象调用它,这是不允许的。

不允许在this以外的对象的派生类中调用受保护的成员函数。获得指针会使其暴力。

我们可以这样做:

#include <iostream>

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

class B : public A {
public:
    void bar()
    {
        void (A::*fptr)() = &A::foo;

        A obj;
        (obj.*fptr)();

        // obj.foo(); //this is not compiled too.    
    }
};

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

答案 2 :(得分:1)

我很好奇并尝试了下面的例子:

#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();
}

实际上,我看到&A::foo == &B::foo,因此对于基类的受保护成员,您可以使用派生类成员来获取地址。我想如果虚函数不起作用