用::显式调用父类函数需写全作用域路径,语法为BaseClass::func(),适用于静态、虚与非虚函数,但虚函数如此调用将绕过动态绑定直接静态决议。

用 :: 显式调用父类函数时,必须写全作用域路径
子类里重写了某个函数,又想在子类实现里复用父类逻辑——这时候不能直接写 func(),否则会递归调用自己。得用作用域解析运算符明确告诉编译器:“我要的是父类那个”。
- 语法是
BaseClass::func(),不是super::func()(C++ 没super) - 如果父类是模板类或有多层继承(比如
GrandParent -> Parent -> Child),必须写最准确的基类名,Parent::func()和GrandParent::func()效果完全不同 - 静态成员函数、虚函数、非虚函数都适用这套写法;但虚函数这么调用会绕过动态绑定,直接走静态决议
示例:
class Base { public: virtual void say() { cout << "Base"; } };<br>class Derived : public Base {<br>public:<br> void say() override {<br> Base::say(); // ✅ 正确:显式调用父类版本<br> cout << " + Derived";<br> }<br>};
虚函数重写后,不加 Base:: 就进不了父类实现
这是新手最容易卡住的地方:明明父类有默认逻辑,子类只改了一小部分,结果一重写就全丢了,还找不到哪儿出问题。
- 只要子类定义了同签名函数(哪怕没加
override),父类的同名函数在子类对象上调用时就不可见了——除非用::显式拉出来 - 编译器不会自动“合并”父类和子类的函数体,也不会默认帮你调一次父类版本
- 如果父类函数是纯虚的(
virtual void f() = 0;),那Base::f()就非法,调用会链接失败
多重继承下,:: 必须指定具体基类,不能省略或模糊
当一个类从多个父类继承,且它们都有同名函数时,不写清楚是哪个父类,编译器直接报错。
立即学习“C++免费学习笔记(深入)”;
- 错误写法:
::func()或Base1::func()但Base1并未声明该函数 - 正确做法:确认函数定义在哪一层,比如
InterfaceA::init()和UtilsMixin::init()是两个完全独立的函数 - 如果两个父类都定义了
void log(),子类里写log()会歧义,必须写成InterfaceA::log()或UtilsMixin::log() - 这种歧义在模板推导或 ADL(参数依赖查找)场景下更容易被掩盖,建议早查早清
调用父类构造函数不是用 ::,而是放在初始化列表里
这是个高频混淆点:函数能用 ::,构造函数不能。写错地方会导致编译失败或逻辑错位。
- 错误:
Base::Base(42);放在子类构造函数体内 —— 这是普通函数调用语法,但构造函数不能这样调 - 正确:
Derived::Derived(int x) : Base(x) { /* 构造体 */ }初始化列表才是唯一合法位置 - 析构函数同理:不能手动写
Base::~Base(),系统会在子类析构完成后自动调用,强行调用是未定义行为 - 如果父类构造函数是 explicit 的,子类初始化列表里也必须显式传参,不能依赖隐式转换
调用父类成员这件事,核心就一条:C++ 不自动帮你“向上找”,所有跨作用域访问都得靠你亲手写清楚路径。漏掉一个 Base::,或者写错一个类名,编译器就停在那里不动——它不会猜,也不会妥协。










