3

我正在为 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();

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

4

9 回答 9

18

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

((GUI_TEXTBOX*)mainGui.activeWindow->activeWidget)->function();  // Extra parentheses
dynamic_cast<GUI_TEXTBOX*>(mainGui.activeWindow->activeWidget)->function();  // C++ style cast
于 2008-12-01T19:43:19.370 回答
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<>() 不能保证在这种情况下工作(尽管在大多数编译器上它们会[但这只是实现的一个方面,你很幸运])。如果分配给 activeWidget 的对象实际上使用多重继承,那么所有的赌注都将被取消,在这种情况下,如果您不使用 dynamic_cast<>(),大多数编译器都会开始出现奇怪的错误。

于 2008-12-01T19:57:56.470 回答
4

你只需要更多的括号:

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

实际上,这也可以:

((GUI_TEXTBOX*)mainGui.activeWindow->activeWidget)->function();
于 2008-12-01T19:42:06.673 回答
3

正如其他人指出的那样:

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

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


我将在此处为“实用 C”中的 Steve Oualline 规则添加另一个插件:

C 中有 15 条优先规则(&& 在 || 之前 ?:)。实用的程序员将这些减少到两个:

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

2)在其他所有内容周围加上括号。


最后一点:向下投射可能很危险,请参阅Martin York 的答案以获取有关使用dynamic_cast<>安全执行投射的信息。

于 2008-12-01T19:44:18.697 回答
1

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

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

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

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

于 2008-12-01T19:45:32.907 回答
1

有两种策略。一种是“快速失败”:如果您转换为错误的类型,那么您将抛出异常,因此您会立即注意到您转换为错误的类型。另一个是“快速运行”:没有检查演员的目标类型。仅当您知道自己不会错或没有基类或派生类的多态类型时,才应使用此强制转换。我根据您的需要推荐以下内容(请记住在投射时保留 const ):

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

快速失败std::bad_cast如果您转换为错误的类型,则抛出。

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

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

于 2008-12-01T21:43:03.620 回答
0
((GUI_TEXTBOX*)(mainGui.activeWindow->activeWidget))->function();
于 2008-12-01T19:42:19.403 回答
0

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

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

于 2008-12-01T19:44:40.863 回答
0
if( GUI_TEXTBOX* ptr = 
      dynamic_cast<GUI_TEXTBOX *>(mainGui.activeWindow->activeWidget) )
{
   ptr->function();
}

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

于 2008-12-01T20:02:50.610 回答