8

ライブラリは仮想関数を持つクラスを提供します。ライブラリに動的にリンクされたバイナリを再コンパイルせずに、このクラスを新しい仮想関数で拡張できますか?クライアントコードを再コンパイルせずに仮想インターフェイスを拡張できますか?

これは標準では不可能です。これを可能にするプラットフォームはありますか?

新しい機能がクラス本体の最後に追加された場合には、それは簡単でしょうか?

+0

私はライブラリインターフェイスを拡張したいと思います。メインライブラリクラスを受け付けるAPI関数のシグネチャを引数として変更せずにこれを達成する別の方法がある場合は、そのことも知りたいと思います。 – Basilevs

+1

KDEプロジェクトの興味深いドキュメントがあります:[C++のバイナリ互換性問題](http://techbase.kde.org/Policies/Binary_Compatibility_Issues_With_C%2B%2B)。読んで興味のある他の2つのドキュメントへのリンク。 – Mat

答えて

5

標準はバイナリ互換性に関係しません。しかし、クラスに関しては、クラスの定義をある翻訳単位から別の翻訳単位に「変更」することで、実際には未定義の動作が呼び出されます。

ほとんどのコンパイラでは、再コンパイルを必要とせずにさまざまな変更が可能ですが、リストは小さいです...これについては、これが可能でない可能性があると私は言うでしょう。は、クラス

私が予期する問題は、コンパイラが通常仮想テーブルで実行する最適化にあります。

はあなたが仮想関数を持つクラスを作成する場合、あなたはそのように見える仮想テーブルを取得:、派生クラス独自の仮想関数は、通常、「追加」されているいくつかのスペースを得るために

// B virtual table 
0 - Offset to complete object 
1 - RTTI 
2 - func0 
3 - func1 
... 

を:

// D virtual table 
Same as B 
N+3 - func(N+1) 
N+4 - func(N+2) 

このようにDオブジェクトのみB(ポインタまたは参照を介して)(静的)タイプであってもそのようなものとして使用することができるよりも、一つの仮想ポインタを有しています。あなたがDを再コンパイルせずBを延長した場合

しかし、それは単なるクラッシュ、BN+1関数を呼び出すとき以来、あなたの代わりに多分、同じ引数を持っていないDN+1関数を呼び出しますでしょう。 ..オップス!

を知っている場合は、派生クラスがない場合は、それ自身の任意の仮想関数を追加することができます。

+2

一部のライブラリは、最後に(通常は 'reserved1'、' reserved2'などと呼ばれる)いくつかの仮想仮想関数を追加するので、後でバイナリ互換性を損なうことなく置き換えることができます。 –

+0

@Jan Hudec:clever :)余分なビットを考えさせる^^ –

+0

あなたが言うように、C++標準にはABI互換性は含まれていません。実際、動的ディスパッチのためのvtableの使用も義務付けていません。これは、ほとんどの(すべての)コンパイラが使用する実装の詳細です。 – rjnilsson

関連する問題