2

GLibなどのCスタイルの継承を使用するCAPIを使用する場合(C構造体の標準レイアウトを利用)、通常はCスタイルのキャストを使用してダウンキャストします。

struct base_object
{
    int x;
    int y;
    int z;
};

struct derived_object
{
    base_object base;
    int foo;
    int bar;
};

void func(base_object* b)
{
    derived_object* d = (derived_object*) b; /* Downcast */
}


しかし、このようなC-APIを使用する新しいC ++コードを記述している場合、Cスタイルのキャストを引き続き使用する必要がありますか、それともC++キャストを優先する必要がありますか?後者の場合、CダウンキャストをエミュレートするためにどのタイプのC ++キャストを使用する必要がありますか?

reinterpret_cast最初、私は適切だと思いました:

derived_object* d = reinterpret_cast<derived_object*>(b);

reinterpret_castただし、 C ++標準では何が起こるかについてほとんど保証されていないため、私は常に警戒しています。static_cast次の目的で使用する方が安全な場合がありますvoid*

derived_object* d = static_cast<derived_object*>(static_cast<void*>(b))

もちろん、これは本当に面倒なので、この場合はCスタイルのキャストを使用する方が良いと思います。

では、ここでのベストプラクティスは何ですか?

4

4 に答える 4

2

このようなC-APIを使用する新しいC++コード

新しいC++コードをCスタイルで記述しないでください。これは、C ++言語機能を利用せず、ラッパーのユーザーにこれと同じ「C」スタイルを使用するように強制します。代わりに、CAPIインターフェイスの詳細をラップしてC++クラスの背後に隠す適切なC++クラスを作成します。

Cスタイルのキャストを引き続き使用する必要があります

いいえ

または、C++キャストを優先する必要があります

はい、ただし必要な場合に限ります。

C ++の継承と仮想アクセサ関数を使用します(おそらく)。funcで派生オブジェクトをどのように使用する予定かを示してください。これにより、より適切な回答が得られる可能性があります。

funcが派生オブジェクトのメソッドを使用することを期待している場合は、派生オブジェクトを受け取る必要があります。base_objectのメソッドを使用することを期待しているが、ポインターがderived_objectを指しているためにメソッドが何らかの形で変更されている場合、仮想関数がこれを行うC++の方法です。

また、ポインタではなく、funcへの参照を渡したいとします。

dynamic_cast、特定の条件を満たす必要があります。

http://www.cplusplus.com/doc/tutorial/typecasting/

structptrsをstructptrsに変換するだけで、必要なものがわかっている場合は、static_castまたはreinterpret_castが最適ですか?

ただし、C ++コードの記述に本当に興味がある場合は、より良いパターンがあるため、キャストを最後の最後の手段にする必要があります。私がキャストを検討する2つの一般的な状況は次のとおりです。

  • 汎用基本クラスをイベントハンドラーに渡すイベント受け渡しメカニズムとインターフェイスしています。

  • オブジェクトのコンテナがあります。コンテナには同種のタイプが含まれている必要があります(つまり、すべての要素に同じ「もの」が含まれています)が、コンテナに異なるタイプを格納する必要があります。

于 2013-03-03T16:26:00.017 に答える
2

ただし、C ++標準では何が起こるかについてほとんど保証されていないため、reinterpret_castには常に注意が必要です。

CスタイルのキャストはC++スタイルのキャストで定義されているため、C++スタイルのキャストはCスタイルのキャストと同じくらい安全です。

5.4.4によって実行される変換

— const_cast(5.2.11)、

— static_cast(5.2.9)、

— static_castの後にconst_castが続き、

— reinterpret_cast(5.2.10)、または

— reinterpret_castの後にconst_castが続き、

明示的な型変換のキャスト表記を使用して実行できます。

[...]

変換が上記の複数の方法で解釈できる場合、その解釈から生じるキャストの形式が正しくない場合でも、リストの最初に表示される解釈が使用されます。

悲しい答えは、コンパイラがクラス間の関係についてほとんど知らないため、あなたが書いたようなコードのキャストを避けることはできないということです。何らかの方法で、それをリファクタリングすることをお勧めします(キャスト、クラス、またはそれらを使用するコード)。

結論は次のとおりです。

可能であれば、適切な継承を使用してください。

できない場合は、reinterpret_castを使用してください。

于 2013-03-03T16:59:38.433 に答える
2

dynamic_castC ++仕様のCスタイルのキャストの仕様を見ると、キャスト表記が他の型変換演算子( 、、、、 )static_castで定義されておりreinterpret_castconst_castこの場合reinterpret_castは使用されていることがわかります。

さらに、reinterpret_castリンク先の回答で示されているよりも多くの保証を提供します。あなたが気にするのは:

§9.2/20:reinterpret_castを使用して適切に変換された、標準レイアウトの構造体オブジェクトへのポインターは、その初期メンバー(または、そのメンバーがビットフィールドの場合は、それが存在するユニット)を指し、その逆も同様です。

キャスト表記を使用する場合は、C++型変換演算子を明示的に使用するのが最適だと思います。ただし、コード全体にキャストを散らかすのではなく、変換ごとに関数を記述して(を使用して実装reinterpret_cast)、それを使用する必要があります。

derived_object *downcast_to_derived(base_object *b) {
    return reinterpret_cast<derived_object*>(b);
}
于 2013-03-03T17:13:45.407 に答える
-1

dynamic_castはまさにあなたが望むものだと思います。

于 2013-03-03T16:54:46.500 に答える