You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++中通过基类暴露派生类私有虚成员的原理探究

C++虚函数私有覆盖后仍可通过基类调用的原因

问题描述

发现一段C++代码,派生类B中将覆盖的虚函数设为私有,但通过基类A的引用却能调用到该私有函数,代码如下:

#include <iostream>
class A {
public:
    virtual void print() const { std::cout << "hello A" << std::endl;}
};

class B: public A {
private:
    void print() const override { std::cout << "hello B" << std::endl;}
};

int main() {
    const A &a = B();
    a.print();  // 输出"hello B",超出预期
    const B &b = B();
    b.print(); // 编译报错,符合预期
}

为何a.print()能够正常执行并输出"hello B"?难道C++在运行时会忽略private/public访问限定符吗?原本以为派生类中print()是私有的,a.print()不会生效。


解答

核心原因在于C++的访问权限检查发生在编译阶段,而动态绑定是运行阶段的行为,二者完全独立:

  • 当通过基类A的引用a调用print()时,编译器在编译阶段只会检查静态类型(即A类)中print()的访问权限——A::print()是public的,因此编译直接通过,不会去管派生类中该函数的权限。
  • 运行阶段,动态绑定机制会根据对象的实际类型(B)找到对应的B::print()实现并执行,此时不会再做任何访问权限检查,因为权限验证已经在编译阶段完成了。

而直接用B类的引用b调用print()时,编译器检查的是**静态类型B**中print()的权限,发现它是private,因此直接触发编译错误,程序根本到不了运行阶段。

简单来说:访问权限看的是调用时的静态类型(引用/指针的类型),动态绑定看的是运行时的实际对象类型,二者互不干扰,这是C++标准规定的行为。


内容的提问来源于stack exchange,提问作者Foma Roje

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 03:42:15