一、源代码
cpp
#include <iostream>
// /*
struct Base
{
virtual void f(){}
};
struct Derived:Base
{
void f() override;
};
int main()
{
Base *p = new Derived;
return 0;
}
关于 polymorph.cpp:9 中 void f() override; 的说明
void f() override; 只是函数声明 ,不是函数定义。没有函数体,与 override 没有关系。
1. 为什么可以没有函数体?
C++ 允许在类中先声明成员函数,再在类外定义:
cpp
struct Derived : Base
{
void f() override; // 声明:告诉编译器有这个函数
};
void Derived::f() // 定义:提供函数体,这里不再写 override
{
std::cout << "Derived::f()\n";
}
也可以直接在类内定义:
cpp
struct Derived : Base
{
void f() override {} // 定义,函数体为空,表示什么也不做
};
注意两种写法的区别:
| 写法 | 含义 |
|---|---|
void f() override; |
只有声明,还没有提供实现 |
void f() override {} |
已经提供实现,只是函数体为空 |
源代码当前只有声明,缺少 Derived::f() 的定义。下方注释掉的示例使用的是第二种写法,所以那里有函数体。
2. override 的作用是什么?
override 是 C++11 引入的说明符,意思是:
"我打算让这个函数重写基类的虚函数,请编译器帮我检查。"
你的基类在 polymorph.cpp:5 中定义了:
cpp
virtual void f() {}
因此,派生类的:
cpp
void f() override;
确实重写了基类的虚函数,检查通过。
如果不小心把参数写错:
cpp
struct Derived : Base
{
void f(int x) override {} // 编译错误:基类中没有对应的虚函数
};
编译器就会指出问题。如果不写 override,这个 f(int) 可以被当作另一个函数,不能达到你想重写 Base::f() 的目的,却不一定报错。
真正使函数具备虚调用行为的是基类的 virtual;override 主要用于检查重写关系、表达意图。正确重写时,即使不写 override,重写关系仍然成立。
3. 当前代码能正常生成程序吗?
不能。我实际编译了当前文件,链接阶段出现:
undefined reference to `vtable for Derived'
原因是 main() 中执行了:
cpp
Base *p = new Derived;
创建 Derived 对象需要其虚函数表,但 Derived::f() 没有定义,因此出现链接错误。即使没有显式调用 p->f(),这里也会出错。
最简单的修正就是把声明改为:
cpp
void f() override {}
总结 :override 负责"检查是否正确重写",不负责生成函数体,也不会自动使用基类的函数体。