




显式调用父类同名函数需用作用域解析符Base::func(),因子类同名函数会遮蔽父类版本;虚函数不解决编译期名字查找遮蔽问题;父类private函数不可在子类中通过Base::调用;默认参数在显式调用时仍生效。
:: 显式调用父类同名函数当子类定义了和父类同名的函数(无论参数是否一致),父类版本会被遮蔽,obj.func() 默认只找子类里的。这时必须用作用域解析符 :: 指明调用路径:Base::func()。
常见错误是以为加 virtual 就能自动回退到父类实现——其实不会,虚函数只控制“动态绑定到哪个版本”,不解决“编译期名字查找被遮蔽”的问题。
BaseClass::function_name(),不能只写 ::function_name()
private,即使在子类内部也不能通过 Base::func() 调用这不是“方法调用”,但常被混淆:父类构造函数只能在子类初始化列表里用 Base(args) 形式调用,不能在构造函数体里用 Base::Base(args) —— 后者语法错误,且会尝试创建临时对象。
典型误写:
Derived() {
Base(42); // ❌ 编译失败:这不是调用父类构造函数,而是声明一个临时 Base 对象
}
Derived() : Base(42) { }
no matching function for call to 'Base::Base()'
重写虚函数时,经常需要“先做父类的事,再加自己的逻辑”。此时必须手动写 Base::func(),编译器不会自动帮你补上。
例如:
class Base {
public:
virtual void log() { std::cout << "Base log\n"; }
};
class Derived : public Base {
public:
void log() override {
Base::log(); // ✅ 显式调用父类实现
std::cout << "Derived extra\n";
}
};Base::log() 是常见疏忽,尤其在调试时发现父类日志没输出= 0),则不能直接调用 Base::pure_func(),除非它有定义(即有函数体)GrandParent::func() 也能跨级调用,只要访问权限允许C++ 的名字查找在进入子类作用域后就停止了,哪怕子类只定义了一个 void f(int),父类的 f(double)、f(const char*) 全部不可见——这不是重载,是遮蔽。
修复方式只有两个:using Base::f; 引入全部重载,或逐个显式转发。
class Derived : public Base {
public:
using Base::f; // ✅ 把父类所有 f 都带进来
void f(int x) { /* 新实现 */ }
};using,又想保留某个父类重载?只能手动写转发:void f(double d) { Base::f(d); }
using 声
父类函数是否可访问、要不要显式调用、会不会被意外遮蔽——这些细节在重构或添加新函数时最容易出问题,尤其是多人协作项目里,一个新增的同名函数可能让其他模块静默失效。