3

異種オブジェクトをヒープに割り当てて呼び出し元に返すファクトリ メソッドを書きたいとします。私はこのようなAPIを設計することを考えています:

bool MakeEm(auto_ptr<Foo>& outFoo, auto_ptr<Bar>& outBar) {
  ...
  if (...) {
    return false;
  }
  outFoo.reset(new Foo(...));
  outBar.reset(new Bar(...));
  return true;
}

これにより、呼び出し元はこれを行うことができます。

auto_ptr<Foo> foo;
auto_ptr<Bar> bar;
MakeEm(foo, bar);

私の質問は、「これは慣用的なものですか?そうでない場合、これを行う正しい方法は何ですか?」です。

struct私が考えることができる代替アプローチには、 のを返すことauto_ptr、またはファクトリ API を記述して生のポインター参照を取得することが含まれます。どちらもより多くのコードを記述する必要があり、後者には例外の安全性に関して他の落とし穴があります。

4

5 に答える 5

4

何かを慣用的に尋ねると、非常に主観的な答えが返ってくることがあります。ただし、一般的には、auto_ptr は所有権を伝えるのに最適な方法だと思います。そのため、クラス ファクトリからのリターンとしては、おそらく良いことです。私はこれをリファクタリングしたいと思います

  1. 2 つではなく 1 つのオブジェクトを返します。非常に緊密に結合された 2 つのオブジェクトが必要な場合は、お互いなしでは存在できません。is-a または has-a リファクタリングの強力なケースがあると思います。
  2. これは C++ です。成功を示す値を返す必要があるかどうかを本当に自問してください。ファクトリのコンシューマは毎回チェックする必要があります。例外をスローするか、ファクトリ内のクラスのコンストラクターから例外を渡します。false を指定して、初期化されていない auto_ptr を操作したいと思うことはありませんか?
于 2011-07-15T18:13:00.500 に答える
1

原則として、 が含まれる場合、auto_ptr慣用的ではありません。一般に、構造はあまり慣用的ではありません。通常、それぞれに対して 1 つの関数を作成し、値によって戻り、失敗した場合は例外をスローし、変数を共有する必要がある場合はオブジェクトにします。

于 2011-07-15T18:10:09.487 に答える
1

falseの戻り値が「出力パラメータを見ない」ことを意味すると仮定しましょう。

次に、bool の戻り値を取り除き、必要な auto_pointers を持つ構造体またはペアをthrowエラー状態で返します。

于 2011-07-15T18:10:44.090 に答える
1

通常、auto_ptr パラメータがある場合、それらは参照ではありません。

これは、auto_ptr を取る関数に何かを渡すと、その関数が所有権を取得することを期待しているためです。参照渡しの場合、実際にはオブジェクトを受け取りません (オブジェクトを受け取る場合があります)。

微妙なポイントですが、最終的には、インターフェイスがユーザーに何を伝えようとしているのかを確認する必要があります。

また、outパラメータとして使用しているようです。
個人的には、この使用例を見たことがありません (しかし、見ることはできます) やろうとしていることと、さらに重要な理由を文書化するだけです。

于 2011-07-15T18:12:06.477 に答える
1

2 つの値を返すために独自の構造体を作成する必要はありません。std::pair を使用できます。その場合、2 つの値を返す際の構文上のオーバーヘッドはあまりありません。このソリューションには、「.first」と「.second」があまりわかりやすい名前ではないという問題がありますが、関連する型と関数の名前が意図を十分に明確にしている場合、それは必ずしも問題ではありません。

C++0x を使用している場合は、auto_ptr の代わりに unique_ptr を使用でき、呼び出し元はより長い std::pair<std::unique_ptr<A>, std::unique_ptr<B>> を入力する代わりに auto を使用できます。C++0x を使用していない場合は、代わりに typedef を使用することを検討してください。

2 つの値を返すと、bool 用のスペースがありません。C++0x タプルを使用して、3 つの値すべてを返すことができます。例外をスローするか、null ポインターを返すことによって、エラーを示すこともできます。エラーがまれ/例外的であると仮定して、例外を希望します。

他の回答が指摘しているように、それぞれが 1 つのオブジェクトを返す 2 つの別個の関数を使用することが望ましいことがよくあります。2 つのオブジェクトの初期化が密接に関連しているためにそれができない場合は、初期化をカプセル化するクラスを作成できます。2 つのオブジェクトを作成するために必要な情報をコンストラクターに渡し (エラーを通知するには例外が必要です)、そのクラスに 2 つのメソッドを用意して、それぞれ 1 つのオブジェクトを生成することができます。

于 2011-07-15T22:07:30.737 に答える