C++ 能否要求派生类至少重写一个虚函数?
数据阿明
结论
C++ 没有语法能要求派生类“至少重写这组虚函数中的一个”。抽象类只能要求派生类实现指定的纯虚函数。比如,render_GET 和 render_POST 都是纯虚函数时,派生类必须同时实现它们。
在题述设计中,http_resource 为各个 render_*METHOD* 提供了默认实现,因此编译器不会要求子类重写这些函数。默认实现调用通用的 render,也不会形成“至少重写一个”的约束。
为什么纯虚函数无法表达“至少一个”
纯虚函数的约束分别作用于每个函数。派生类只要有一个纯虚函数尚未实现,就仍是抽象类,不能直接实例化。C++ 没有“多个虚函数任选一个实现”的内建规则。
例如,下面的接口要求派生类实现两个函数:
struct Resource {
virtual void render_GET() = 0;
virtual void render_POST() = 0;
};
如果为这两个函数都提供默认实现,编译器就不再要求派生类重写它们。虚函数机制也无法在编译时检查派生类重写了哪个函数。
可选的接口设计
如果可以调整基类接口,可以改为要求派生类实现一个统一的纯虚函数,再让基类的默认方法调用它:
struct Resource {
virtual void render() = 0;
virtual void render_GET() {
render();
}
virtual void render_POST() {
render();
}
};
这样能确保子类实现 render(),但要求的是实现统一入口,并非要求它重写 render_GET 或 render_POST 中的一个。如果必须保留按请求方法分别重写的接口,可以在运行时显式登记支持的方法,并在请求到达时检查。编译器不会验证这类运行时约束。
选择方案时
- 如果所有子类都能使用同一入口,可以用纯虚函数
render()提供编译期约束。 - 如果子类需要分别处理不同请求方法,就需要接受默认实现不会强制重写,或自行设计运行时检查、注册等机制。
final、重载和普通虚函数声明都不能表达“这组函数至少重写一个”。
备注:内容仅供参考。
