この状況に遭遇している間、私はC ++を学んでいます。そこでは、Cで次のシンボリックコードの同等に効率的なバージョンをC++で実装したいと考えています。
<header.h>
struct Obj;
Obj* create(...);
void do_some_thing(Obj*);
void do_another_thing(Obj*);
void destroy(Obj*);
要件は次のとおりです。
- 実装はライブラリ(静的/動的)で提供され、ヘッダーはインターフェイス以外の詳細を公開しません
- 同様に効率的である必要があります
仮想関数を使用してインターフェース(COMのようなもの)を公開することはできません。これは、ポリモーフィズム(同じインターフェイスを介して公開される複数の実装)を有効にするソリューションですが、そうではありません。それがもたらす価値は必要ないため、関数の呼び出しにかかるコストを支払う必要がある理由がわかりません。 2つの間接ポインタを介して。だから私の次の考えは、単純なイディオムでした:
<header.h>
class Obj {
public:
Obj();
~Obj();
void do_some_thing();
void do_another_thing();
private:
class Impl;
smart_ptr<Impl> impl_; // ! What should I use here, unique_ptr<> or shared_ptr<> ?
};
shared_ptr <>は適格ではないようです。元の実装には存在しなかった、不要なインターロックされたインクリメント/デクリメントに対して支払います。一方、unique_ptr <>を使用すると、Objをコピーできなくなります。つまり、クライアントはObjを値で受け取る独自の関数を呼び出すことができず、Objは単なるポインターのラッパーであるため、基本的にポインターを値で渡すことはできません。彼は元のバージョンでそれを行うことができました。(参照による受け渡しはまだ適格ではありません:彼はまだポインターをポインターに渡しています)
では、これをC++で実装するための同様に効率的な方法は何でしょうか。
編集:私はそれにもう少し考えを与え、私はこの解決策に到達しました:
<header.h>
class ObjRef // I exist only to provide an interface to implementation
{ // (without virtual functions and their double-level indirect pointers)
public:
ObjRef();
ObjRef(ObjRef); // I simply copy pointers value
ObjRef operator=(ObjRef); // ...
void do_some_thing();
void do_another_thing();
protected:
class Impl;
Impl* impl_; // raw pointer here, I'm not responsible for lifetime management
};
class Obj : public ObjRef
{
Obj(Obj const&); // I'm not copyable
Obj& operator=(Obj const&); // or assignable
public:
Obj(Obj&&); // but I'm movable (I'll have to implement unique_ptr<> functionality)
Obj& operator=(Obj&&);
Obj();
~Obj(); // I destroy impl_
// and expose the interface of ObjRef through inheritance
};
ここで、クライアントObjに戻ります。クライアントが他の関数を呼び出して、Objの使用法を配布する必要がある場合、彼はそれらを次のように宣言できます。
void use_obj(ObjRef o);
// and call them:
Obj o = call_my_lib_factory();
use_obj(o);