2
struct B { 
  virtual void foo ()
  { cout << "B::foo()\n"; }
};

struct D : B { 
  void foo () //final
  { cout << "D::foo()\n"; }
};

int main ()
{
  B *pB = new B;
  D *pD = static_cast<D*>(pB);
  pB->foo();
  pD->foo();
}

予想される動作を出力します。

B::foo()
B::foo()

D::foo()ファイナルを作成すると、出力は快適に異なります。

B::foo()
D::foo()

これは、virtualそのメソッドが として宣言されているクラスのポインター/参照でメソッドが呼び出されたときに、機能が開始されないことを意味しますfinal
またfinal、コンパイル時のチェックだけでなく、実行時の動作にも寄与することを意味します。

これはすべてのコンパイラの標準的な動作ですか。g++4.7 でテストしました。

編集:明確化し
新しい質問を作成しました。この質問を閉じます。

4

3 に答える 3

11
D *pD = static_cast<D*>(pB);

このステートメントにより、あなたは正常なプログラム動作を行う権利を放棄しました。C++ では、指定されたものが実際の型でない場合、またはの派生クラスの 1 つでない場合 (そうでない場合)、この操作が機能する必要はありません。static_castDD

したがって、あなたを妨げているのは最適化ではなく、単に悪いコードです。

存在する理由がdynamic_castあります。適切なキャストdynamic_castはこれですぐに失敗しnullptr、不正なキャストに戻ります。

于 2012-11-01T02:47:11.397 に答える
5

オブジェクトの実際の型ではない型へのポインタ/参照を介してオブジェクトにアクセスしているため、未定義の動作の領域に入っています。

3.10 [basic.lval] p10

プログラムが、次の型以外の glvalue を介してオブジェクトの格納された値にアクセスしようとした場合、動作は未定義です。

  • オブジェクトの動的タイプ
  • [...]

の動的タイプpBBase*明らかに ですが、 の動的タイプpD依然として Base*です。

于 2012-11-01T02:48:30.790 に答える
3

ここで未定義の動作を呼び出しています。ポインタを勝手にダウンキャストすることはできません。

于 2012-11-01T02:43:50.227 に答える