2008-12-01 53 views
3

我正在为C++构建一个GUI类,并且使用指针处理很多事情。一个例子电话:我在做什么这个指针错误吗?

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

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

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

这不起作用,因为编译器仍然认为指针的类型是GUI_BASE。然而,下面的一段代码确实有效:

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

我希望我的问题在这里只是一个语法问题。感谢您的帮助:)

+0

C++样式提示:ALL_CAPS通常保留用于预处理器定义。我在boost邮件列表中为一个模板参数使用了全部大写名称,因此我的屁股突然发生了一次,而且它仍然很疼。 – 2008-12-01 20:26:40

回答

18

的问题是,强制转换比优先级低。 - >()[]运算符。你必须使用C++风格的转换或增加额外的括号:

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

如果GUI_TEXTBOX是从GUI_BASE派生的,那么应该使用dynamic_cast <>() – 2008-12-01 19:54:23

+0

哎呀,好的调用 - 谢谢。 – 2008-12-01 19:58:35

4

你只是需要更多的括号:

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

事实上,这将工作太:

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

你几秒钟就打败我了! – 2008-12-01 19:52:44

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

正如其他人指出:

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

的原因是->操作符比型铸造一个更高的优先级。


我把另一个插件在这里从“实用C”史蒂夫·林的规则:

有在 C(& & 15条优先规则来||来 前过吗? :)。实际编程人员将这两个数字减为 :

1)加法和减法之前的乘除法来得到 。

2)把其他的东西放在所有的东西 。


而且最后要注意的:向下转换可能是危险的,看到Martin York's answer的信息,使用dynamic_cast<>安全地执行转换。

1

这是一个操作符的顺序问题(操作符优先级)。考虑你所尝试的代码是行不通的:

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

这里,->运算符的优先级高于您的转换。这就是为什么你的其他代码示例有效。在另一个示例中,您首先明确施放,然后调用该函数。为了使它更精简尝试添加另一组括号,使代码如下:

((GUI_TEXTBOX *)(mainGui.activeWindow-> activeWidget)) - >()函数;

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 <>(),那么您将看到大多数编译器出现奇怪的错误。

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

你想这样做的原因是因为你想投的指针可能不实际指向GUI_TEXTBOX对象,并要确保调用它的文本框方法之前它。 C++的动态转换就是你需要的。

1

有两种策略。一种是“快速失败”:如果你投下了错误的类型,那么你将会抛出一个异常,所以你会立即注意到你投下了错误的类型。另一个是“跑得快”:没有检查演员的目标类型。只有当你知道你不可能是错的,或者你没有基类或派生类的多态类型时,才应该使用这个类型。我建议根据您的需要以下(记得要保持常量,当你施放):

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

Fail fast:抛出std::bad_cast如果你投了错误的类型。

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

Run fast:不执行运行时检查。所以它不会快速失败。相反,如果投射到错误的类型,它会产生未定义的行为。谨防!

相关问题