2012-02-16 10 views
3

私はDLLから複数のクラスをエクスポートするC++ APIを開発中です。出力パラメータとしてshared_ptrを使用する

パブリッククラスインターフェイスは、次の規則に従う必要があります。

  • すべての関数はエラーコードを返します。
  • 出力パラメータは、追加の戻り値として使用されます。
  • 出力パラメータには、ポインタによるパスが使用されます。
  • constによる参照は、入力パラメータ(プリミティブ型の値渡し)に使用されます。
  • 出力パラメータの所有権をクライアントが取得する必要がある場合は、shared_ptrが使用されます。そうでない場合は、通常のポインタが使用されます。

例インタフェース:

typedef std::shared_ptr<Object> ObjectPtr; 

class APIClass 
{ 
    ErrorCode SetSomething(int i); 
    ErrorCode IsSomethingSet(bool* ask); 
    ErrorCode DoSomething(); 
    ErrorCode GetSomething(ObjectPtr* outObj); 
} 

使用例:

ErrorCode res; 
ObjectPtr obj; 
res = myApiClass->GetSomething(&obj); 

GetSomething実装:

ErrorCode APIClass::GetSomething(ObjectPtr* outObj) 
{ 
    ObjectPtr temp(new Object(), CleanUpFunction<Object>); 

    // Do something with object temp. 
    ... 

    *outObj= temp; 

    return OK; 
} 

それがこの方法でのshared_ptrを使用するために保存するかが可能ですです私が知っておくべき問題?

+1

エラーコードを返す代わりに、[例外](http://www.parashift.com/c++-faq-lite/exceptions.html)を使用したことがありますか? –

+0

はい、DLLの境界を越えて例外を使用するため、例外を使用したくありません。 – Hoschie0815

+0

あまりにも冗長であるため、質問を編集しました。 – Hoschie0815

答えて

1

これは問題ありませんが、この場合は共有ポインタが本当に必要かどうかを尋ねます。ほとんどの場合、shared_ptrからのポインタを正常な方法で解放できないため、後で問題になる可能性があります。 shared_ptrは実際には、基本となるリソースの不特定または共有の所有権を意味します。

私は、通常の機能を文書化し、のようなものを使用します。この方法で、それは彼らがにポインタを格納したいクライアント次第であり、オブジェクトの所有権がに渡すことは明らかである

// Caller must delete the outObj once done. 
ErrorCode APIClass::GetSomething(Object* & outObj) 
{ 
    // I use auto_ptr so I can release it later... 
    // Mostly I hate auto_ptr, but for this its invaluable. 

    auto_ptr<Object> obj(new Object); 
    ... 
    outObj = obj.release(); 
    return OK; 
} 

を発信者。

クライアントコードでは、適切なコンテナを使用できます。

// Caller must delete the return value. 
// On error, NULL is returned and e filled in appropriately. 
Object* APIClass::GetSomething(ErrorCode & e) 
{ 
    auto_ptr<Object> obj(new Object); 
    .. 
    e = OK; 
    return obj.release(); 
} 

//Now using it looks like this: 
ErrorCode ec; 
shared_ptr<Object> obj(apiObject.GetSomething(ec)); 
if(!obj) 
{ 
    .. do something with ec .. 
} 
:これはあなたがあなたの関数の定義を変更した場合すっきり行うことができることを

Object * obj_raw; 
ErrorCode ec = apiClass.GetSomething(obj_raw) 
if(ec!=OK) { .. do something with ec .. } 
shared_ptr<Object> obj(obj_raw); 

または

auto_ptr<Object> obj(obj_raw); 

または

scoped_ptr<Object> obj(obj_raw); 

など

注意

+0

返事をありがとう。 DLLの境界(少なくともWindowsでは)にポインタを渡すことに問題があります。 DLLにメモリを割り当て、クライアント側でメモリを削除します。ここをクリックしてください:http://msdn.microsoft。com/ja/us/library/ms235460.aspx。そのため、shared_ptrを作成するときに、DLL(CleanUpFunction )で定義されているカスタムのDeleterを使用しています。 – Hoschie0815

+0

しかし、一般的に私が理解しているように、ソリューションはうまくいくはずだと思いますか?どのような場合には、後でポインタを放すことができない場合、またはそれをなぜ放棄したいのですか? – Hoschie0815

+0

また、このようなオプションのパラメータとしてエラーコードを渡すことで言及したような代替デザインについて考えていました。ObjectPtr APIClass :: GetSomething(ErrorCode * e = nullptr)しかし、どのデザインが良いかはまだ決めることができませんでした。 – Hoschie0815

関連する問題