#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
也有效。能否解释为什么我们无法得到基类的受保护成员函数的地址?
答案 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
,因此对于基类的受保护成员,您可以使用派生类成员来获取地址。我想如果虚函数不起作用