首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >关于从基类到子类指针的下转换

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

Stack Overflow用户
提问于 2010-09-30 15:56:35
回答 3查看 10.1K关注 0票数 5

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

代码语言:javascript
复制
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’

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

的好处:允许转换继承层次结构的会导致维护问题,而从基类降级总是非法的。

参考文献:

  1. Scott,“有效的C++:改进您的程序和设计的50种具体方法”,第二版,Addison,(C) 2005 Pearson Education,Inc.,一章:“继承和面向对象的设计”,第39项
  2. 联合打击战斗机、飞行器、C++编码标准-第4.23章-倒置,AV规则178

您认为不将基类指针转换为子类指针是一个很好的实践吗?我为什么和什么时候应该遵循这个规则?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-10-06 02:53:04

让我们看一下MFC中的一些下拉式示例:

CButton*来自CWnd*

代码语言:javascript
复制
CWnd* wnd = GetDlgItem(IDC_BUTTON_ID);
CButton* btn = dynamic_cast<CButton*>(wnd);

CChildWnd*来自CFrameWnd*

代码语言:javascript
复制
CChildWnd * pChild = ((CSplitFrame*)(AfxGetApp()->m_pMainWnd))->GetActive();

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

由于CWnd提供了MFC中所有窗口类的基本功能,它甚至充当视图、对话框、按钮等的基类。

如果我们想避免降级,我们可能需要MFC黑客将CWnd分解成更少的碎片?

现在,谈到另一个问题,如何解决违规行为,我的看法是尽量避免不安全的下线,通过使用安全下线:

代码语言:javascript
复制
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

downcasting.html

最后,感谢大家的各种有益回应。

它们确实很有帮助。

票数 4
EN

Stack Overflow用户

发布于 2010-09-30 16:00:58

reinterpret_cast在这里肯定是个坏主意,不管编码标准还是OOP理论。它必须是dynamic_cast下浇

至于有效C++的第39章,它集中讨论了由于必须降到多个不同类型并必须检查dynamic_cast的返回值以确定潜在故障而导致的维护问题,从而导致代码中的多个分支:

重要的是:如果-然后-如果-然后-其他风格的编程不可避免地导致是远远低于使用虚拟函数,你应该保留它的情况下,你真的没有其他选择。

票数 10
EN

Stack Overflow用户

发布于 2010-10-03 22:44:53

在我看来,这并不是真的有必要让你去表演演员表演,或者至少不是你正在做的那样。您的函数需要返回一个CWnd,因此不需要转换到CSplitFrame

我本以为GetChildWnd会返回一个CWnd*或类似的内容;为什么您不能写这样的东西:

代码语言:javascript
复制
CWnd* CVsApp::GetSheetView(LPCSTR WindowText)
{
   return m_pMainWnd->m_OutputBar.GetChildWnd(WindowText);
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3832420

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档