10

仮想および非仮想メンバー関数によってアクセスされる、多数のプライベート データ メンバー (一部は静的) を持つクラスがあります。インライン関数もフレンド クラスもありません。

class A
{
    int number;
    string str;
    static const int static_const_number;
    bool b;
public:
    A();
    virtual ~A();
public:
    // got virtual and non-virtual functions, working with these memebers
    virtual void func1();
    void func2();

    // no inline functions or friends
};

この場合、プライベート データ メンバーの順序を変更すると ABI が壊れますか?

class A
{
    string str;
    static const int static_const_number;
    int number; // <--   integer member moved here
    bool b;
    ...
};


編集
タイプは変更されず、メンバーの順序のみが変更されます。ビット フラグも使用されません。コードは共有ライブラリとして使用され、このコードへの静的リンクはありません。私は Linux を使用しており、コンパイラは gcc-3.4.3 と gcc-4.1 です。

4

4 に答える 4

12

はい、それ以外の理由がない場合はA、データメンバー間のパディングバイトの場所と数の違いにより、のサイズが異なる可能性があります。

于 2010-05-31T15:09:30.140 に答える
5

KDE Policies/Binary Compatibility Issues With C++によると、バイナリ互換性を壊さずにそれを行うことはできません。ただし、免責事項に記載されているように、「できません...」の部分で提供されるアドバイスの一部はコンパイラに依存するため、その変更を回避する可能性があります (可能性は低いですが)。

于 2010-05-31T15:33:55.257 に答える
3

C++はABiを定義していません。ここでの唯一の正解は「コンパイラによって異なります」です。答えはおそらくイエスです。

于 2010-05-31T15:11:13.610 に答える
3

実装が複数のバイナリにコンパイルされている場所では、おそらく壊れます。これは、順序の異なるプライベートメンバーにアクセスする関数を持つ2つのバイナリになってしまう可能性があるためです。これには、仮想関数の実装も含まれます。これは、オーバーライドされていない実装を複数のバイナリにコンパイルすることもできるためです。

最良の方法は、純粋仮想関数を使用し、これらを「ホスト」バイナリからのインターフェースとして公開することです。その場合、追加のバイナリは実装を必要としないため、常に「ホスト」バイナリで実装を呼び出します。これは、矛盾の余地がないことを意味します。

于 2010-05-31T15:12:55.887 に答える