为什么基类指针(或引用)可以调用派生类的private虚函数

本文探讨了在C++中基类的public虚函数被派生类重写为private时,为何仍可通过基类指针调用派生类的虚函数。解析了vptr和vtable的工作原理,并解释了编译器如何忽略派生类中虚函数的访问控制。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在基类中定义了public虚函数,在派生类中将其重写,但是设置为private,为什么通过基类指针仍然可以发生动态绑定调用派生类中的private虚函数?

例子如下:

class Base
{
public:
    // public虚函数
    virtual void Disp() { cout << "base.\n"; }
};
 
class Derived : public Base
{
private:
    // 重写基类虚函数,但是放在private中
    virtual void Disp() { cout << "derived.\n"; }
};
 
void main()
{
    Derived Dobj;
    Base *pBase = &Dobj;
    pBase->Disp();    // 显示的结果是派生类的虚函数被调用!
}
正确的解释:派生类中虚函数的访问权限是在编译阶段由基类确定的,在运行阶段不再检查访问权限,所以,虚函数的访问权限与派生类就没关系了。


更进一步的解释:当pBase->Disp()时,首先通过这个对象的vptr找到对应的vtable, 因为它实际上是Derived对象,所以找到的是Derived的虚表,所有的Derived对象都共用这个虚表。又因为是通过基类的指针调用的,编译器从Base的类型信息中查到Disp是虚表中的第一个entry, 而且这个函数的访问权限是public的,所以首先它让你调用,其次,从虚表第一个entry中取出的函数地址对应着Derived::Disp, 所以最后是Derived::Disp被调用,Derived::Disp在Derived中的访问权限在这里是无关的了,编译器根本不会费事去查询这一信息。甚至这一信息可能根本编译器也不知道。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值