C での Static_cast によるダウンキャスト
ダウンキャストは、基底クラスのポインターまたは派生クラスへの参照をキャストするためにオブジェクト指向プログラミングで使用される手法です。クラスポインタまたは参照。 C では、これは static_cast 演算子を使用して実現できます。
次のコード例を考えてみましょう:
class Base { public: Base() {} virtual void func(); }; class Derived : public Base { public: Derived() {} void func(); void func_d(); int a; }; int main() { Base *b = new Base(); std::cout << sizeof(*b) << std::endl; // Prints 4 Derived *d = static_cast<Derived *>(b); std::cout << sizeof(*d) << std::endl; // Prints 8 d->func_d(); }
この例では、Base 型のポインターが作成され、次のオブジェクトで初期化されます。タイプベース。 sizeof 演算子は Base オブジェクトのサイズを示す 4 を返します。
ただし、static_cast を使用して b を Derived 型のポインターにキャストし、それを d に代入しようとすると、*d のサイズは 8 になります。これは派生オブジェクトのサイズです。通常、*d のサイズは *b のサイズと同じであると予想されるため、この動作は予期せぬものです。
この動作の理由は、未定義動作 (UB) の概念にあります。 static_cast を使用してオブジェクトを実際には持たない型にキャストすると、UB が生成されます。この場合、 b は Derived オブジェクトではなく Base オブジェクトを指します。 Static_cast はオブジェクトの基になる型を変更できないため、キャストの結果は未定義です。
C 標準のセクション 5.2.9 ([expr.static.cast]) では、ダウンキャストのルールが指定されています。 using static_cast: "タイプ 'cv1 B へのポインタ' の prvalue が、実際にはタイプ D のオブジェクトのサブオブジェクトである B を指している場合、結果のポインタは、型 D のオブジェクトを囲んでいます。それ以外の場合、キャストの結果は未定義です。"
この場合、b が指す Base オブジェクトは Derived オブジェクトのサブオブジェクトではないため、キャストの結果はは未定義です。 UB の症状は大きく異なる可能性があり、派生メンバー関数 (func_d) が正常に呼び出せるという保証はありません。
以上がC でのダウンキャストに「static_cast」を使用すると、どのような場合に未定義の動作が行われますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。