const是函数签名的必要组成部分,void func() const与void func()是两个不同签名;虚函数重写必须完全匹配,包括const限定符,否则视为新函数而非重写,加override可提前捕获此类错误。

const 是函数签名的一部分,不是可选修饰
在 C++ 中,void func() const 和 void func() 是两个完全不同的函数签名。虚函数重写要求“完全匹配”,const 限定符属于签名构成要素,漏掉或多余都会导致重写失败——编译器认为你定义了一个新函数,而不是重写基类虚函数。
常见错误:基类有 const,派生类没写 const
这种 mismatch 最容易静默发生,尤其当基类接口由他人维护时。现象是:调用时看似走多态,实际执行基类实现,且不报错(除非加了 override)。
- 基类声明:
virtual void process(const std::string& s) const; - 派生类错误写法:
void process(const std::string& s) { ... }(缺const)→ 新函数,非重写 - 派生类正确写法:
void process(const std::string& s) const override { ... }
const 影响 this 指针类型,进而影响重载与绑定
const 成员函数的 this 类型是 const T*,而非 T*。这意味着:
- 它和非 const 版本天然构成重载关系,哪怕其他部分全一样
- 若基类虚函数带
const,派生类必须也带,否则无法满足“同一签名”要求 - 即使参数列表、返回值、noexcept 都一致,仅 this 的 cv-qualifier 不同,就不是重写
为什么 override 能帮你提前发现问题
不加 override 时,上面所有 const 不匹配的情况都可能编译通过,但运行时调用的是基类版本;加上后,编译器立刻报错,例如:
error: 'process' does not override any member function
这说明你写的函数在基类中找不到匹配的虚函数——大概率就是 const、&、noexcept 或参数类型差了一点点。
最容易被忽略的是:const 修饰的是整个函数语义(不可修改对象状态),不是“加不加都行”的风格选项。它参与虚表索引计算,也参与重载决议,漏掉一个 const,虚函数机制就断开了。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











