翻译《有关编程、重构及其他的终极问题?》——24.override和final关键字应该成为你的新朋友

翻译《有关编程、重构及其他的终极问题?》——24.override和final关键字应该成为你的新朋友

标签(空格分隔): 翻译 技术 C/C++
作者:Andrey Karpov
翻译者:顾笑群 - Rafael Gu
最后更新:2017年04月26日


24.override和final关键字应该成为你的新朋友

下面这段代码来自MFC库。PVS-Studio检查到的错误描述为:V301 Unexpected function overloading behavior. See first argument of function ‘WinHelpW’ in derived class ‘CFrameWndEx’ and base class ‘CWnd’(译者注:大意为异常的函数重载行为,请参看‘CFrameWndEx’子类和‘CWnd’基类‘WinHelpW’函数的第一个参数)。

class CWnd : public CCmdTarget {
  ....
  virtual void WinHelp(DWORD_PTR dwData,
                       UINT nCmd = HELP_CONTEXT);
  ....
};
class CFrameWnd : public CWnd {
  ....
};
class CFrameWndEx : public CFrameWnd {
  ....
  virtual void WinHelp(DWORD dwData,
                       UINT nCmd = HELP_CONTEXT);
  ....
};

解释
当你重载一个虚函数时,在在符号差异上是比较容易犯错的,比如在子类中定义一个与基类函数看似无关联的新函数,在这种情况下,这会产生各种错误提示:
1. 在重载的函数中,参数使用了其他类型。
2. 在重载的函数中有不同数量的参数个数,这对于有多个参数的情况非常重要。
3. 在重构的函数中const关键字用法不同。
4. 基类函数并非虚函数,这种情况假定子类的函数会重载基类的对应函数,但实际上却屏蔽了它。

当程序员改变了整个继承结构中的虚函数的各种符号而忘了修改其对应的子类函数时,相关于参数类型和质量修改的错误就会在已知代码中出现。

这个错误特别容易在把移动移植到64位平台的情况下发生,比如用DWORD_PTR替换DWORD类型,用LONG_PTR替换LONG类型等。这里查看更多细节。这其实就是我们上面错误发生的情况。

即使在上面错误的情况下,在32位系统下仍然能正常工作,因为DWORD和DWORD_PTR都是和unsigned long意义相同的(译者注:即unsigned long的别名);但在64位版本上就会发生错误,因为DWORD_PTR是和unsigned __int64相同意义的。

正确的代码

class CFrameWndEx : public CFrameWnd {
  ....
  virtual void WinHelp(DWORD_PTR dwData,
                       UINT nCmd = HELP_CONTEXT) override;
  ....
};

建议
现在,我们有了新的方法来防止我们犯下前面所说的错误,在C++ 11中增加了两个新的关键字:

  • Override - 表示修饰的函数重载了基类中的一个虚函数
  • Final - 表示子类中不能(再)重载这个函数

这里我们对override关键字感兴趣,它告诉编译器去检查对应的虚函数是否真的重载了基类中的对应函数,如果没有就会报错。

如果override关键字在CFrameWndEx类的WinHelp中被使用了,我们在编译64位版本的应用程序时就会得到一个错误,这样,这个错误其实就能尽早的被发现(译者注:然后被修正)。

当使用可重载的虚函数时,请无比使用override关键字(或者final关键字)。更多关于override和final关键字的知识可以看下面:

猜你喜欢

转载自blog.csdn.net/headman/article/details/70790235
今日推荐