接口实现与私有继承的交互:私有继承成员间接访问疑问
私有继承下通过基类指针访问虚函数的可见性问题
你提到的这个情况其实挺有意思的,核心原因在于C++的访问控制是编译时规则,而虚函数的动态调用是运行时行为,两者完全不在一个阶段工作,所以才会出现这种看似“绕过”权限的情况。
先补全你给出的代码示例(方便理解完整场景):
#include <iostream> using std::cout; class R { public: virtual void doWork() = 0; }; class RA : public virtual R { public: void doWork() override { cout << "RA's doWork implementation\n"; } }; class AD : private RA { // 私有继承RA,理论上RA的所有成员在AD里都是私有属性 }; int main() { AD ad_obj; R* r_ptr = &ad_obj; // 合法的类型转换 r_ptr->doWork(); // 成功调用到RA::doWork return 0; }
下面拆解关键逻辑:
- 编译时的访问检查:当你用
R*指针调用doWork()时,编译器只会检查指针所属类(R)中该成员的可见性。因为R的doWork是public的,所以编译阶段完全合法,不会报错。至于AD私有继承RA这件事,编译器在这个调用场景下根本不会去查——它只认当前指针的类型规则。 - 运行时的虚函数绑定:编译通过后,程序运行时会通过虚表找到实际的函数实现(也就是RA::doWork)。而运行时是没有访问权限检查的——访问控制的元信息在编译完成后就被丢弃了,运行时只负责找到对应的函数地址并执行,不管这个函数所在的类在子类中的继承权限。
另外要明确:如果直接尝试在AD类外部调用ad_obj.doWork(),编译一定会失败——因为AD私有继承了RA,doWork在AD中属于私有成员,编译时就会被拦截。但通过基类指针的方式,相当于绕开了对AD类成员可见性的直接检查,只触发了基类R的可见性检查。
内容的提问来源于stack exchange,提问作者Josh
相关产品推荐
相关产品推荐

