簡體   English   中英

這個指針轉換我在做什么錯?

[英]What am I doing wrong with this pointer cast?

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

我希望我的問題只是語法問題。 謝謝您的幫助 :)

問題在於類型轉換的優先級低於。 ->()[]運算符。 您必須使用C ++樣式轉換或添加額外的括號:

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

您不應該使用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 <>(),則對於大多數編譯器來說,您將開始看到奇怪的錯誤。

您只需要更多的括號即可:

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

實際上,這也可以工作:

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

正如其他人指出的那樣:

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

原因是->運算符的優先級高於類型轉換。


我將在此處插入“ Practical C”中的史蒂夫·奧特林規則的另一個插件:

C中有15個優先規則(&&在||之前在?:之前)。 實用的程序員將這些簡化為兩個:

1)乘法和除法先於加法和減法。

2)在其他所有內容上加上括號。


最后一點:向下轉換可能很危險,有關使用dynamic_cast<>安全執行轉換的信息,請參閱Martin York的答案

這是運算符順序的問題(運算符優先級)。 考慮一下您嘗試的無效代碼:

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

在這里, ->運算符的優先級比您的強制轉換高。 這就是您其他代碼示例起作用的原因。 在另一個示例中,您首先顯式強制轉換,然后調用該函數。 為了使其更加簡化,請嘗試添加另一組括號,使代碼如下所示:

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

有兩種策略。 一種是“快速失敗”:如果您將類型強制轉換為錯誤類型,則將引發異常,因此您將立即注意到您將類型強制轉換為錯誤類型。 另一個是“快速運行”:不檢查強制轉換的目標類型。 僅當您知道自己不會記錯或者您的基數或派生類型不具有多態類型時,才應使用此強制類型轉換。 我根據您的需求建議以下內容(轉換時請記住保持const):

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

快速失敗 :如果轉換為錯誤類型,則拋出std::bad_cast

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

快速運行 :不執行運行時檢查。 因此它不會很快失敗。 相反,如果轉換為錯誤的類型,它將產生未定義的行為。 謹防!

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

->比(cast)具有更高的優先級,因此在進行強制轉換之前已完成成員訪問。 有關操作員優先級的信息,請參見此處: http : //www.cppreference.com/wiki/operator_precedence

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

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

之所以這樣做,是因為您嘗試投射的指針實際上可能未指向GUI_TEXTBOX對象,並且您想確保在調用該對象之前要確保它確實指向該對象。 為此,您需要C ++的動態轉換。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM