当心虚函数重载(overloaded-virtual)
(转载请注明来源于金庆的专栏)
为网游万王之王3(KOK3)服务器添加新功能的时候,
发现某个类成员函数应该是const函数, 因为我的const函数要调用该函数,
顺手就加上了const.
再顺便看到该类有好多个明显是getter函数, 所以都加上了const.
编译没错就提交了.
结果没多久测试就发现了新版本的一个错误, 表现在其他功能上,
但由同事纠错后发现是我添加const的后果.
原来添加const的成员函数中, 有一个是virtual函数, 加了const后与子类的函数原型就不符了.
子类的函数成为父类虚函数的一个重载, 使virtual失效, 多态性无法表现出来.
解决方法就是子类的相应虚函数中也添加const.
教训: 更改虚函数原型时, 必须同时更改父类和子类.
gcc中有个-Woverloaded-virtual警告选项, 会报告这种虚函数重载.
我在Makefile中打开了-Woverloaded-virtual, 再次编译时就产生了许多警告.
大多数警告是正确的函数重载, 但还是发现了一个与我相同的错误,
这次是函数参数const有区别, 我发给相关人员处理了.
因为开了-Werror, 所有警告都会造成编译失败,
所以我们不能在Makefile中加入-Woverloaded-virtual警告选项.
代码示例:
class A
{
virtual void f() {};
};
class B : public A
{
virtual void f() const {};
};
int main()
{
return 0;
}
$ g++ main.cpp -Woverloaded-virtual
main.cpp:3: warning: `virtual void A::f()' was hidden
main.cpp:8: warning: by `virtual void B::f() const'
Google的代码规范中要求所有子类的虚函数中都加上virtual, 是很有道理的.
虽然只要与父类虚函数签名相同, 加不加virtual都是虚函数,
但是以后更改函数签名时, 看到virtual很容易知道它是虚函数, 需要父类子类同时更改.