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();

その理由は、->演算子は型キャストよりも優先順位が高いためです。


「PracticalC」からのSteveOuallineのルールのために、ここに別のプラグインを配置します。

Cには15の優先順位ルールがあります(&&は||が前に来る?:)。実用的なプログラマーは、これらを2つに減らします。

1)乗算と除算は、加算と減算の前に行われます。

2)他のすべてを括弧で囲みます。


そして最後の注意:ダウンキャストは危険な場合があります。キャストを安全に実行するために使用する方法については、MartinYorkの回答を参照してください。dynamic_cast<>

于 2008-12-01T19:44:18.697 に答える
1

これは、演算子の順序の問題です (演算子の優先順位)。うまくいかなかったコードを考えてみましょう:

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

ここでは、->演算子はキャストよりも優先されます。それが、他のコード サンプルが機能する理由です。もう 1 つのサンプルでは、​​最初に明示的にキャストしてから、関数を呼び出します。より合理化するには、コードが次のようになるように、別の括弧のセットを追加してみてください。

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

于 2008-12-01T19:45:32.907 に答える
1

2 つの戦略があります。1 つは「フェイル ファスト」です。間違った型にキャストすると、例外がスローされるため、間違った型にキャストしたことがすぐにわかります。もう 1 つは「高速実行」です。キャストの宛先タイプのチェックは行われません。このキャストは、間違っていないことがわかっている場合、またはベースまたは派生物にポリモーフィック型がない場合にのみ使用してください。必要に応じて次のことをお勧めします (キャストするときは const を保持することを忘れないでください)。

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

Fail faststd::bad_cast :間違った型にキャストするとスロー

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

Run fast : ランタイム チェックを行いません。そのため、すぐに失敗することはありません。むしろ、間違った型にキャストすると、未定義の動作が発生します。注意してください!

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

->は(キャスト)よりも優先順位が高いため、メンバーのアクセスはキャストの前に行われます。演算子の優先順位については、こちらを参照してください: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 に答える