学习C++函数重写(或函数覆盖)时,发现跟Java有些不一样,这里简单记录一下,方便自己查阅。
正文
下面分别介绍一下。
C++
在C++中,重写并非默认行为,而是需要显式声明的契约。其核心在于区分“重写”与“隐藏”。
重写
只有当基类函数被virtual修饰,且派生类函数签名(名称、参数、const限定符)完全一致时,才构成重写。
C++11引入的override关键字是防御性编程的关键,它强制编译器检查重写合法性,避免因拼写错误或参数不匹配导致的意外隐藏。
动态绑定,调用时由指向的对象决定!
class Base { public: virtual void overrideFunc() { cout << "Base::overrideFunc (虚函数)" << endl; } }; class Derived : public Base { public: void overrideFunc() override { cout << "Derived::overrideFunc (重写)" << endl; } }; int main() { Base* ptr = new Derived(); // 重写:动态绑定,调用派生类版本 ptr->overrideFunc(); // 输出: Derived::overrideFunc (重写) delete ptr; return 0; }
虚函数,动态绑定,指向了子类,调用子类重写的函数、
隐藏
若基类函数非虚,或派生类函数仅同名但参数不同,则发生隐藏。
隐藏是编译期静态绑定,通过基类指针调用时始终执行基类版本,与对象实际类型无关。
静态绑定:对于非虚函数,编译器在编译期就根据指针/引用的声明类型(即
Base*)决定了调用目标。
class Base { public: void hideFunc() { cout << "Base::hideFunc (非虚)" << endl; } }; class Derived : public Base { public: void hideFunc() { cout << "Derived::hideFunc (隐藏)" << endl; } }; int main() { Base* ptr = new Derived(); ptr->hideFunc(); // 输出: Base::hideFunc (非虚) delete ptr; return 0; }
普通函数,不支持动态绑定。
静态绑定,编译器在编译期就根据指针/引用的声明类型(即 Base*)决定了调用目标函数。
也就是看哪个类声明的,不是看指向的对象类型!
小结
| 基类函数 | 绑定方式 | 调用依据 | 输出结果 |
|---|---|---|---|
void hideFunc() | 静态绑定 | 指针声明类型 Base* | Base::hideFunc |
virtual void hideFunc() | 动态绑定 | 对象实际类型 Derived | Derived::hideFunc |
Java
Java的设计目标是简化面向对象编程,因此消除了C++中的隐藏机制,将所有实例方法默认为虚函数。
对比
| 场景 | C++ | Java |
|---|---|---|
| 启用多态 | 基类必须加virtual | 无需任何关键字 |
| 防止误写隐藏 | 派生类必须加override | 推荐加@Override(仅编译检查) |
| 同名不同参 | 触发隐藏,非多态 | 触发重载,非隐藏 |
| 访问父类被重写方法 | Base::func() | super.func() |
AI

