C++如何实现函数重写(override)?(继承与多态)

函数重写要求基类函数声明为virtual,派生类函数签名一致、返回类型协变,并推荐使用override关键字;非virtual函数同名仅构成隐藏,不实现多态。

在C++中,函数重写(override)是指派生类中重新定义基类的虚函数,以实现运行时多态。关键在于:基类函数必须声明为 virtual,派生类函数需满足签名一致、返回类型协变,并显式使用 override 关键字(推荐,C++11起支持)。

基类必须有 virtual 函数

只有被 virtual 修饰的成员函数才能被正确重写。非 virtual 函数即使名字相同,也只是隐藏(hiding),不构成多态。

例如:

class Base {
  public:
    virtual void show() { cout     void func() { cout };

派生类重写要满足三个条件

重写函数必须与基类虚函数:

  • 函数名、参数列表(类型、数量、顺序)完全相同
  • 返回类型相同,或满足协变要求(如都返回指针/引用,且派生类返回更具体的类型)
  • 常量性(const 修饰符)和引用限定符(& / &&)也需一致

推荐加上 override 关键字,编译器会检查是否真正重写了虚函数,避免拼写错误或签名不匹配导致的静默失败。

class Derived : public Base {
  public:
    void show() override { cout     // void show(int) override { ... } // ❌ 参数不同,不是重写,编译报错
};

通过基类指针/引用调用实现多态

重写的真正意义在于:用基类指针或引用指向派生类对象时,调用的是派生类版本的函数——这就是运行时多态。

Base* ptr = new Derived();
ptr->show(); // 输出 "Derived",不是 "Base"
delete ptr;

注意:基类析构函数也应声明为 virtual,否则 delete 基类指针时不会调用派生类析构函数,可能引发资源泄漏。

常见误区提醒

  • 忘记加 virtualoverride —— 代码可能“看起来像重写”,实际是隐藏或编译失败
  • 参数类型看似相同但有隐式转换(如 int vs size_t)—— 签名不匹配,不算重写
  • 返回类型不协变(如基类返回 Base*,派生类返回 int)—— 编译错误
  • 把重写(override)和重载(overload)、隐藏(hiding)混淆

基本上就这些。写对 virtual 和 override,保证签名一致,再用基类引用来调用,多态就自然发生了。