2

次のコードのような状況で、ポリモーフィック クラスで static_cast を使用した後、仮想関数を安全に呼び出すことができますか、それとも UB ですか?

#include <iostream>

class Base
{
public:
   virtual void foo() { std::cout << "Base::foo() \n"; }
};

class Derived : public Base
{
public:
   virtual void foo() { std::cout << "Derived::foo() \n"; }
};

int main()
{
   Base* derived = new Derived;
   Derived* _1 = static_cast<Derived*>(derived);
   _1->foo();
}
4

4 に答える 4

6

はい、できます。あなたの特定の例ではそれを行う意味がわかりませんが。と呼ぶだけで

derived->foo();

キャストがなければ、まったく同じ効果が得られます。static_castつまり、その場合、仮想呼び出しメカニズムによって暗黙のうちに何らかの処理が実行されます。

static_castあなたの呼び出しの「仮想」の性質を決して抑制しないことに注意してください。

それは実際、あなたの質問が本当に何についてなのか疑問に思います。なぜあなたはそれについて尋ねるのですか?あなたは何をしようとしているのですか?あなたのコードサンプルでは、​​あなたがやろうとしていることを本当に代表していますか?

于 2012-10-22T17:36:31.467 に答える
2

コンパイラが許可しstatic_cast、実行時にオブジェクトの動的型が期待どおりであれば、はい、できます。問題は、なぜそれをやりたいのかということです...

于 2012-10-22T17:39:11.370 に答える
1

はい、しかし他の人が言ったように、仮想関数を呼び出すためにポインターを派生型にキャストする必要はありません。

dynamic_castただし、継承されたクラスを処理する場合は、通常、使用する方が安全です。を使用dynamic_castすると、実行時に型情報が正しくない場合に適切なエラーが生成されます。

Derived* d = dynamic_cast<Derived*>(derived); //safer, but still unnecessary in this situation 
于 2012-10-22T17:43:59.553 に答える
0

書かれているように、基本的にderived Derived*. したがって、キャストが行っていることは、既に知っていることをコンパイラーに伝えることだけです。繰り返しになりますが、静的キャストがなくても、最終的にDerived::fooは出力になります。したがって、これはやや無意味です。それでも、変数の実際のインスタンス化された型を知っていて、何らかの理由でいくつかの非仮想メンバーにアクセスする必要があると確信している状況では、これを行う必要があるかもしれません。たとえば、不適切に設計されたクラスライブラリを使用している場合...

しかし、一般的に、静的なダウンキャストは悪い考えです。ではない変数をダウンキャストしようとしてしまう可能性があります。そのDerived*場合、仮想 (または非仮想) 関数を呼び出す (または、実際には、ほとんどすべての重要な操作にそのポインターを使用する) と、未定義の動作が発生します。

于 2012-10-22T17:42:33.583 に答える