文章目录在意为改写的函数添加 override未添加 override显式添加 override引用限定符在意为改写的函数添加 override虚函数改写Overriding是实现多态的核心但它的隐式匹配规则非常严苛。如果开发者稍有疏忽本意是“改写Override”的函数就会变成“重载Overload”或“隐藏Hide”而编译器对此往往保持沉默。虚函数改写的严格条件在 C 中派生类函数要想真正改写基类的虚函数必须满足以下所有条件函数名相同。形参类型完全相同。常量性const属性完全相同。返回值类型和异常规格Exception specification必须兼容。(C11 新增)引用限定符Reference qualifiers完全相同。未添加overrideclassBase{public:virtualvoiddoWork();// 基础虚函数virtualvoidprocess(intx);// 带参数virtualvoiddisplay()const;// const 函数};classDerived:publicBase{public:// 错误 1漏掉了 const变成了一个全新的虚函数隐藏了 Base::doWorkvirtualvoiddoWork();// 错误 2参数类型写错int 变成了 unsigned int变成了重载Overloadvirtualvoidprocess(unsignedintx);// 错误 3函数名大小写写错变成了完全无关的新函数virtualvoidDisPlay()const;};:::color4编译期无警告****上述Derived中的三个函数在 C98/C11 语法下完全合法。编译器会认为你是故意在派生类里增加新函数的。运行时行为诡异多态失效:::Base*bpnewDerived();bp-process(10);// 期望调用 Derived::process但实际上调用了 Base::process显式添加override通过在派生类函数后面加上override关键字向编译器明确传达了意图“我这个函数绝对是改写基类的请帮我检查”classDerivedCorrected:publicBase{public:// 编译期报错Base 中没有非 const 的 doWork()voiddoWork()override;// 编译期报错Base 中没有接收 unsigned int 的 processvoidprocess(unsignedintx)override;// 编译期报错Base 中没有名为 DisPlay 的函数voidDisPlay()constoverride;// ---------------- 正确的改写 ----------------voiddisplay()constoverride;// 完美匹配编译通过};为什么强制使用 override让编译器做打字工只要有任何一处不匹配比如漏了const改了参数类型编译器会立刻拒绝编译并给出精准的错误提示。无成本的代码文档任何阅读代码的人一眼就能看出哪些函数是多态的关键节点无需频繁跳回基类去确认。安全重构基类如果哪天你需要修改基类Base::doWork()的签名比如加个参数所有未同步修改的派生类都会在编译期报警而不会在运行时悄悄崩溃。引用限定符C11 允许根据对象是左值还是右值来调用不同的成员函数。如果基类指定了引用限定符派生类改写时也必须完全一致否则也会变成全新的函数。classWidget{public:// 只有左值对象 (*this 是左值) 才能调用此函数virtualvoiddata();// 只有右值对象 (*this 是右值) 才能调用此函数virtualvoiddata();};classSubWidget:publicWidget{public:// 如果不加 override这只是一个没有引用限定的新函数会隐藏 Widget::data// 加上 override 后编译器会立刻发现你漏掉了 或 从而报错voiddata()override;// 错误无法通过编译voiddata()override;// 正确成功改写左值版本};