2

従来のプロジェクターで作業しているときに、ネットワーク経由でデータを転送するために POD 構造体が使用されているというパターンに出会いました。

struct PODType {
    // some data
    int data;
};

受信側では、データは POD タイプのオブジェクトに受信されます。その後、PODType からクラスが派生し、受信したオブジェクトが C スタイルのキャストで派生クラスにキャストされ、データにアクセスするいくつかのメソッドが使用されます。

class DerivedFromPOD: public PODType {
public:
    // some methods
    int f(int x) {return data+x;}
protected:
    // some methods
};

PODType pod;
receive(&pod);

DerivedFromPOD* d = (DerivedFromPOD*)&pod;
int i = d->f(10);

派生クラスにはパブリック メソッドとプロテクト メソッドがあるため、もはや POD ではありません。これが継承の悪用であることはわかっていますが、長い間コード ベースにありました。

それが標準的な観点から動作することが保証されているかどうか疑問に思っています (C++03 または C++98)。派生クラスには独自のデータ メンバーや仮想関数はありませんが、一方が POD で他方がそうでない場合、メモリ レイアウトが同一であることが保証されているかどうかはわかりません。d.dataコンパイラは、POD 基本クラスの場合と同様に、DerivedFromPOD 型のオブジェクト d のアドレスと のアドレスが同じになるように DerivedFromPOD を配置する必要がありますか?

4

2 に答える 2

2

一般的に動作することは確かに保証されておらず (派生クラスに仮想関数を追加してみてください)、正式には未定義の動作です。(また、ネットワーク経由でデータを転送するために a を使用する方法もわかりませんstruct。異なるマシンでは、異なる方法で表現されます。)

于 2014-05-13T12:26:55.327 に答える
1

ポインターは安全にポインターDerivedFromPOD*にキャストできPODType*ます。PODTypeしたがって、継承されたメモリ内のレイアウトは同じであることが保証されます。

ただし、反対方向にキャストする場合は、DerivedFromPODいくつかのコンパイラ データ、次にデータ、さらにいくつかの追加のコンパイラ データを使用してメモリ内で構成できPODTypeます。

C スタイルのキャストを使用している場合、またはstatic_cast<>このキャストの場合、コンパイラは、ユーザーが何をしているのかを知っていると想定し、ポインタ アドレスを調整して、 のPODType部分がDerivedFromPOD適切な領域を正しく指すようにします。

DerivedFromPODただし、メモリ内で正しくないため、他のデータにアクセスするメソッドを使用しないでください。

特に、VMT (仮想メソッド テーブル)がないため、仮想メソッドを使用しないでください。

于 2014-05-13T12:56:42.607 に答える