【问题标题】:Protected member function address in derived class is not accessible派生类中受保护的成员函数地址不可访问
【发布时间】:2015-04-21 18:39:15
【问题描述】:
#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 更改为公共工程。也打印&amp;B::foo 作品。你能解释一下为什么我们不能得到基类的受保护成员函数的地址吗?

【问题讨论】:

  • 好问题。似乎是未来的更正!

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


【解决方案1】:

B 被允许访问A 的受保护成员,只要访问是通过B 类型的对象执行的。在您的示例中,您尝试通过A 访问foo,在这种情况下,B 是否派生自A 无关紧要。

从 N3337,§11.4/1 [class.protected]

当非静态数据成员或非静态成员函数是其命名类 (11.2) 的受保护成员时,将应用第 11 条中所述之外的附加访问检查。 之前,授予对受保护成员的访问权限,因为引用发生在朋友或某个类C 的成员中。如果访问要形成一个指向成员的指针 (5.3.1),则 nested-name-specifier 应表示 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 形成指向受保护成员的指针是错误的。

【讨论】:

  • 有人能解释一下int B::* pmi_B的语法吗? pmi_Bpmi_B2 是 int 值还是指针?你为什么在星号之前叫B::
【解决方案2】:

似乎我找到了答案。如果我们可以得到成员函数的指针,我们可以为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();
}

【讨论】:

    【解决方案3】:

    我很好奇并尝试了以下示例:

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

    实际上,我看到&amp;A::foo == &amp;B::foo,所以对于基类的受保护成员,您可以使用派生类成员来获取地址。我想在虚拟功能的情况下这将不起作用

    【讨论】:

      猜你喜欢
      • 2018-11-27
      • 1970-01-01
      • 2023-03-18
      • 2014-08-27
      • 2013-10-21
      • 1970-01-01
      • 2020-12-24
      相关资源
      最近更新 更多