这个指针演员我做错了什么?

时间:2008-12-01 19:40:19

标签: c++ pointers

我正在为C ++构建一个GUI类,并处理很多指针。一个示例电话:

mainGui.activeWindow->activeWidget->init();

我的问题是我想将 activeWidget 指针转换为另一种类型。 activeWidget 的类型为GUI_BASE。派生自BASE我有其他类,如GUI_BUTTON和GUI_TEXTBOX。我想将 activeWidget 指针从GUI_BASE转换为GUI_TEXTBOX。我认为它看起来像这样:

(GUI_TEXTBOX*)(mainGui.activeWindow->activeWidget)->function();

这不起作用,因为编译器仍然认为指针是GUI_BASE类型。但是,下面的代码可以正常工作:

GUI_TEXTBOX *textbox_pointer;
textbox_pointer = (GUI_TEXTBOX*)mainGui.activeWindow->activeWidget;
textbox_pointer->function();

我希望我的问题只是一个语法问题。谢谢你的帮助:)

9 个答案:

答案 0 :(得分:18)

问题是演员阵容的优先级低于。 - > ()[]运算符。您必须使用C ++样式转换或添加额外的括号:

((GUI_TEXTBOX*)mainGui.activeWindow->activeWidget)->function();  // Extra parentheses
dynamic_cast<GUI_TEXTBOX*>(mainGui.activeWindow->activeWidget)->function();  // C++ style cast

答案 1 :(得分:9)

你不应该使用C风格的演员。

您需要使用C ++动态转换。这将允许您在调用该方法之前测试该对象实际上是GUI_TEXTBOX。

GUI_TEXTBOX* textboxPointer  = dynamic_cast<GUI_TEXTBOX*>(mainGui.activeWindow->activeWidget);
if (textboxPointer)
{
     // If activeWidget is not a text box then dynamic_cast
     // will return a NULL.
     textboxPointer->textBoxMethod();
}

// or 

dynamic_cast<GUI_TEXTBOX&>(*mainGui.activeWindow->activeWidget).textBoxMethod();

// This will throw bad_cast if the activeWidget is not a GUI_TEXTBOX

请注意,C样式转换和reinterpret_cast&lt;&gt;()不能保证在这种情况下工作(虽然在大多数编译器中它们会[但这只是实现的一个方面而且你很幸运])。如果分配给activeWidget的对象实际使用多重继承,则所有投注都会关闭,在这种情况下,如果您不使用dynamic_cast&lt;&gt;(),您将开始看到大多数编译器的奇怪错误。

答案 2 :(得分:4)

您只需要更多括号:

((GUI_TEXTBOX*)(mainGui.activeWindow->activeWidget))->function();

实际上,这也可行:

((GUI_TEXTBOX*)mainGui.activeWindow->activeWidget)->function();

答案 3 :(得分:3)

正如其他人所说:

((GUI_TEXTBOX*)(mainGui.activeWindow->activeWidget))->function();

原因是->运算符的优先级高于类型转换。


我会在这里为Steve Oualline的“Practical C”规则添加另一个插件:

  

有十五个优先规则   C(&amp;&amp; to before ||之前来过   ?:)。实用的程序员减少了   这两个:

     

1)乘法和除法来   在加法和减法之前。

     

2)将括号括在一切   其他


最后一点:转发可能很危险,有关使用dynamic_cast<>安全执行演员的信息,请参阅Martin York's answer

答案 4 :(得分:1)

这是运营商的顺序问题(运营商优先级)。考虑一下您尝试的代码无效:

  

(GUI_TEXTBOX *)(mainGui.activeWindow-&GT; activeWidget) - &GT;功能();

此处,->运算符的优先级高于您的强制转换。这就是你的其他代码示例有效的原因。在另一个示例中,您先显式转换,然后调用该函数。为了使其更加简化,请尝试添加另一组括号,以便代码如下所示:

  

((GUI_TEXTBOX *)(mainGui.activeWindow-&GT; activeWidget)) - &GT;功能();

答案 5 :(得分:1)

有两种策略。一个是“快速失败”:如果你转换为错误的类型,那么你将抛出一个异常,所以你会立即注意到你转换为错误的类型。另一个是“快跑”:没有检查演员表的目的地类型。只有在您知道自己没有错误或者您没有基数或派生的多态类型时,才应使用此强制转换。我根据你的需要推荐以下内容(记得你在演员时保持const):

dynamic_cast<GUI_TEXTBOX&>(*mainGui.activeWindow->activeWidget).function();

Fail fast:如果您使用了错误的类型,则会抛出std::bad_cast

static_cast<GUI_TEXTBOX*>(mainGui.activeWindow->activeWidget)->function();

Run fast:不进行运行时检查。所以它不会快速失败。相反,如果转换为错误的类型,它将产生未定义的行为。小心!

答案 6 :(得分:0)

((GUI_TEXTBOX*)(mainGui.activeWindow->activeWidget))->function();

答案 7 :(得分:0)

- &GT;具有比(强制转换)更高的优先级,因此成员访问在转换之前完成。请参阅此处了解运算符优先级:http://www.cppreference.com/wiki/operator_precedence

如上所述,您需要更多括号。

答案 8 :(得分:0)

if( GUI_TEXTBOX* ptr = 
      dynamic_cast<GUI_TEXTBOX *>(mainGui.activeWindow->activeWidget) )
{
   ptr->function();
}

您想要这样做的原因是因为您尝试强制转换的指针可能实际上并未指向GUI_TEXTBOX对象,并且您希望在对其调用文本框方法之前确保它。 C ++的动态演员是你需要的。