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

静态检查工具显示违反以下代码:
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;
}
错误消息:类'CSplitFrame'继承自'CWnd'类 描述:避免强制转换继承层次结构。 此规则检测从基类指针到子类指针的强制类型转换。 好处:允许强制转换继承层次结构会导致维护问题,而从基类进行向下转换始终是非法的。   参考文献:         Scott Meyers,“有效的C ++:50种改进程序和设计的具体方法”,第二版,Addison-Wesley,(C)2005 Pearson Education,Inc。,章节:“继承和面向对象设计”,第39项   联合攻击手,空中车辆,C ++编码标准第4.23章类型转换,AV规则178    你认为不从基类指针转换为子类指针是一个好习惯吗?为什么以及何时应遵循此规则?     
已邀请:
无论编码标准或OOP理论如何,
reinterpret_cast
在这里肯定是一个坏主意。它必须是
dynamic_cast
或boost :: polymorphic_downcast。 至于Effective C ++的第39章,它集中讨论由于必须向下转换为多种不同类型而导致的维护问题,并且必须检查
dynamic_cast
的返回值以查找潜在的故障,从而导致代码中的多个分支:   重要的是:if-then-else的编程方式,即向下转换总是导致它远远低于虚函数的使用,你应该在你真正无可奈何的情况下保留它。     
让我们来看看MFC中的一些向下转换示例: 来自CWnd *的CButton *
CWnd* wnd = GetDlgItem(IDC_BUTTON_ID);
CButton* btn = dynamic_cast<CButton*>(wnd);
来自CFrameWnd *的CChildWnd *
CChildWnd * pChild = ((CSplitFrame*)(AfxGetApp()->m_pMainWnd))->GetActive();
确实有一些MFC设计的局限性。 由于CWnd提供了MFC中所有窗口类的基本功能,它甚至可以作为View,Dialog,Button等的基类。 如果我们想避免向下转发,我们可能需要MFC黑客将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
它是使用安全向下转换的良好做法,即使违规行为仍然存在,我们也会根据给定的解释来压制违规行为。 几个有用的参考: 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 最后,感谢各位的各种有用回应。 他们确实非常有帮助。     
它看起来并不像你实际上有必要进行演员表演,或者至少不像你一样。你的功能需要返回一个
CWnd
,所以你不需要cast8ѭ。 我原以为
GetChildWnd
会返回
CWnd*
或类似的东西;为什么你不能这样写:
CWnd* CVsApp::GetSheetView(LPCSTR WindowText)
{
   return m_pMainWnd->m_OutputBar.GetChildWnd(WindowText);
}
    
在适当设计的OOP代码中,倾向于通常应该避免使用向下转换类指针。尽管如此,有时候这样的强制转换是必要的,特别是如果你使用的是其他一些设计用于在客户端代码中需要这些强制转换的库/代码。 MFC就是这种库的一个例子。 当真正需要向下倾斜时,它们永远不应该用
reinterpret_cast
来执行。执行演员表的正确方法是
dynamic_cast
static_cast
。 很多时候人们在代码中看到用于向下转换的C风格转换时会使用
reinterpret_cast
并决定将其转换为C ++风格的转换,错误地认为在这种情况下C风格转换等同于
reinterpret_cast
。实际上,在任何方向上应用于父子类型对的C风格转换相当于
static_cast
并且有一些额外的特权(C风格的转换可以突破访问保护)。所以,再次,为此目的使用C风格的强制转换是错误的,但正确的C ++替换不是
reinterpret_cast
,而是
dynamic_cast
static_cast
。     

要回复问题请先登录注册