关于从基类到子类指针的向下转换

wen*_*eng 5 c++ mfc static-analysis casting effective-c++

静态检查工具显示违反以下代码:

class CSplitFrame : public CFrameWnd  
...
class CVsApp : public CWinApp
CWnd* CVsApp::GetSheetView(LPCSTR WindowText)
{
 CWnd* pWnd = reinterpret_cast<CSplitFrame*>(m_pMainWnd)->m_OutputBar.GetChildWnd(WindowText);
 return pWnd;
}
Run Code Online (Sandbox Code Playgroud)

错误消息:类'CSplitFrame'继承自'CWnd'类

描述:避免强制转换继承层次结构.此规则检测从基类指针到子类指针的强制类型转换.

好处:允许强制转换继承层次结构会导致维护问题,而从基类进行向下转换始终是非法的.

参考文献:

  1. Scott Meyers,"有效的C++:50种改进程序和设计的具体方法",第二版,Addison-Wesley,(C)2005 Pearson Education,Inc.,章节:"继承和面向对象设计",第39项
  2. 联合攻击手,空中车辆,C++编码标准第4.23章类型转换,AV规则178

你认为不从基类指针转换为子类指针是一个好习惯吗?为什么以及何时应遵循此规则?

Cub*_*bbi 10

reinterpret_cast无论编码标准还是OOP理论,这都是一个坏主意.它必须是dynamic_castboost :: polymorphic_downcast.

作为有效的C++的第39章,它集中于引起不必向下转换到多种不同类型的并具有检查的返回值的维护问题dynamic_cast的潜在故障,从而导致代码的多个分支:

最重要的是这样的:向下转换总是编程的if-then-else的风格导致远比不上使用的虚函数,你应该保留它在你真的别无选择的情况.

  • 或者`static_cast`,如果已知对象的动态类型. (4认同)
  • 实际上,我说的是误导.如果已知`*p`为`T`,则可以安全地使用`static_cast <T*>(p)`.对于那种情况,`T`不一定是动态类型的`*p`.`T`也可能是动态类型`*p`的基类和静态类型`*p`的派生类.`T`不一定是动态类型的`*p`. (3认同)

wen*_*eng 4

让我们看一下 MFC 中的一些向下转型示例:

来自 CWnd* 的 CButton*

CWnd* wnd = GetDlgItem(IDC_BUTTON_ID);
CButton* btn = dynamic_cast<CButton*>(wnd);
Run Code Online (Sandbox Code Playgroud)

来自 CFrameWnd* 的 CChildWnd*

CChildWnd * pChild = ((CSplitFrame*)(AfxGetApp()->m_pMainWnd))->GetActive();
Run Code Online (Sandbox Code Playgroud)

MFC设计确实存在一些局限性。

由于CWnd提供了MFC中所有窗口类的基本功能,它甚至可以作为View、Dialog、Button等的基类。

如果我们想避免向下转型,可能我们需要 MFC hacker 将 CWnd 分成更少的部分?

现在,谈到另一个问题,如何解决违规问题,我的拙见是尝试通过使用安全向下转型来避免不安全向下转型:

Parent *pParent = new Parent;
Parent *pChild = new Child;

Child *p1 = static_cast<Child*>(pParent);   // Unsafe downcasting:it assigns the address of a base-class object (Parent) to a derived class (Child) pointer
Parent *p2 = static_cast<Child*>(pChild);   // Safe downcasting:it assigns the address of a derived-class object to a base-class pointer
Run Code Online (Sandbox Code Playgroud)

它是使用安全向下转型的良好实践,即使违规行为仍然存在,我们也会通过给出的解释来抑制违规行为。

一些有用的参考:
http://support.microsoft.com/kb/108587
http://blog.csdn.net/ecai/archive/2004/06/26/27458.aspx
http://www.codeproject。 com/KB/mcpp/castingbasics.aspx
http://www.bogotobogo.com/cplusplus/upcasting_downcasting.html

最后,感谢大家的各种有用的回复。
他们确实非常有帮助。