2

共有ライブラリのリビジョン1には、次のABIを維持するために必要な構造体があります。

struct Person
{
    std::string first_name;
    std::string last_name;
}

リビジョン2では、Personを次のように変更しています。

class Person
{
public:
    Person(const std::string &f, const std::string &l);

    std::string first_name;
    std::string last_name;
}

ソースの互換性を維持するために、Personのバージョン1を変更して、新しいヘッダーファイルに対してコンパイルされたコードが実行され、再コンパイルされていないコードが実行されるようにします。

2つの新しい非インラインコンストラクターを使用して次のことを実行できますか?

class Person
{
public:
    Person();
    Person(const std::string &f, const std::string &l);

    std::string first_name;
    std::string last_name;
}

これはすべてg++で行っています。生成された共有ライブラリをnmで見ると、プレーン構造体のコンストラクタまたはデストラクタが表示されないため、再コンパイルされないコードは、以前と同じように呼び出し元のサイトでPersonを構築するだけだと思います。再コンパイルされるコードはすべて、引数なしのコンストラクターを使用します。

私が目にする唯一の問題は、コンストラクターを持たない古いバージョンの共有ライブラリにロールバックする必要がある場合、それに対してコンパイルされたコードはすべて壊れますが、この状況については心配していません。

4

5 に答える 5

3

以下はどうですか?

class NewPerson : public Person
{
public:
    NewPerson(const std::string &f, const std::string &l)
    {
      first_name = f;
      last_name = l;
    }
}
于 2010-08-05T22:01:24.007 に答える
2

それは「機能する」かもしれませんが、1 つの定義ルールに違反することになり、C++ 標準に関する限り、未定義の動作の領域に移行することになります。これは適切な場所ではありません。

于 2010-08-05T21:43:41.490 に答える
1

明示的なデフォルトの ctor が以前に使用された暗黙的な ctor と同じことを行うと仮定すると、うまくいくはずだと思います。この簡単な例では。ただし、コンパイラが何をするか/変更するかを予測したり知ったりするのは難しいです。私があなただったら、私はそれを自分で信用しません。ライブラリのユーザーを再コンパイルしたいと思います。

于 2010-08-05T21:40:45.297 に答える
0

バイナリ互換性を損なうことなく、クラスまたは構造体に新しい非仮想関数を問題なく追加できるはずです。これは、クラス関数がthis、最初のパラメーターとして暗黙的を受け取る通常の関数として実装されているためです。

ただし、新しい仮想関数を追加すると、新しい関数によって vtable が強制的に変更され、互換性が失われる可能性があるため、互換性が失われる可能性があります。

そのため、追加のコンストラクター (仮想にすることはできません) を追加しても、互換性が損なわれることはありません。仮想デストラクタを追加すると、おそらく互換性が失われます。

于 2010-08-05T22:32:21.043 に答える