2008-12-01 84 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:不執行運行時檢查。所以它不會快速失敗。相反,如果投射到錯誤的類型,它會產生未定義的行爲。謹防!

相關問題