web-dev-qa-db-ja.com

RTTIが無効になっているdynamic_cast

RTTIが無効になっている動的キャスト(GCCの-fno-rttiまたはVisualStudioの/GR-のいずれか)を使用してコードをコンパイルするとどうなるか知りたいです。コンパイラはstatic_castに「フォールバック」しますか? (少なくともVSでは)警告を出すだけなので、コンパイルされたコードは何をしますか?

具体的には、このようなdynamic_castでエラーが発生しないと確信しているコード(つまり、dynamic_caststatic_castに安全に置き換えることができるコード)をRTTIなしでコンパイルすると、どのような悪いことが起こる可能性がありますか。 1 :

class A{ /*...*/ } ;
class B : public A {
    int foo() { return 42 ;}
} ;
//...
A * myA = new B() ;
int bar = (dynamic_cast<B*>(myA))->foo() ;
23
Louen

見つける最も簡単な方法はそれを試すことです。

動的キャストの一部に違法のフラグが付けられることがわかります。一部はしません。たとえば、動的キャストを使用して明確な基本クラスにアップキャストすると、コンパイル時に変換が認識されます。

補遺
Re "(少なくともVSでは)警告のみを発行するため..."危険にさらされている警告は無視してください。最善の方法は、警告レベルを非常に高く設定して(場合によってはエラーに変換して)、コードが警告なしでコンパイルされるようにすることです。次善の策は、受け取ったすべての警告を調べて、不利なことが起こらないようにすることです。この場合、厄介なことが起こります。その厄介なイベントがどのように実装されているかを気にする必要はありません。あなたが気にかけるべきことはそれを取り除くことです。

6
David Hammen

標準を読むと、5.2.7/6で、ターゲットがソースの明確なベースでない限り、ソースはポリモーフィック型でなければならないことがわかります。その後、10.3/1で

仮想関数は、動的バインディングとオブジェクト指向プログラミングをサポートします。仮想関数を宣言または継承するクラスは、ポリモーフィッククラスと呼ばれます。

言い換えれば、標準はあなたの質問について何も言っていないようです。この場合、標準ではコンパイラがRTTIをオフにすることを許可していないため、コンパイラごとにドキュメントをチェックして何が起こるかを確認する必要があります。この読みに基づいて、これはコンパイラの質問であり、タグが示すようにC++言語の質問ではないと思います。

または、十分であることがわかっているときにstatic_castを使用するだけで、問題を完全に回避できます。

12
Mark B

MSVCでは、コードがRTTIを有効にしてコンパイルされていない場合、__non_rtti_object実行時チェックなしでキャストを実行できない場合、例外がスローされます。

8
John Dibling