2

その場合に迷子にならないようにするには?たとえば、これはboolを返す関数ですが、10個のパラメータを取ります。

bool myFunc(bool par1 = true, bool par2 = false, bool par3 = true,
  bool par4 = true /* and so on */ ) {}

そして、関数paramsが90%の場合にデフォルトに設定されているとしましょう。しかし、クライアントコードがそれらのいくつかだけを変更したい場合があります。ここに表示される唯一のオプションは、変更が必要なパラメータに到達するまで、すべてのデフォルトのパラメータを入念にコピーすることです。この方法でこの関数を呼び出す可能性:

bool myVal = myFunc(par10 = true, par20 = false);

したがって、コードを読む人は誰でも、コードで何が起こっているのか(パラメーターの名前は非常に長いですが意味があります)を知っています。さらに、関数定義を変更すると、デフォルトのパラメーターを更新するために呼び出されるたびに調べる必要はありませんか?

4

5 に答える 5

11

適度に有名なイディオムがあります:名前付きパラメーターイディオム。

アイデアは単純です:

class Parameters {
public:
    Parameters(): _1(true), _2(false), _3(true), _4(true) {}

    bool get1() const { return _1; }
    bool get2() const { return _2; }
    bool get3() const { return _3; }
    bool get4() const { return _4; }

    Parameters& set1(bool t) { _1 = t; return *this; }
    Parameters& set2(bool t) { _2 = t; return *this; }
    Parameters& set3(bool t) { _3 = t; return *this; }
    Parameters& set4(bool t) { _4 = t; return *this; }

private:
    bool _1;
    bool _2;
    bool _3;
    bool _4;
};

bool myFunc(Parameters p);

次に、クライアントは次のことができます。

result = myFunc(Parameters());

または:

result = myFunc(Parameters().set4(false));
于 2012-12-21T16:38:26.990 に答える
2

boost.parameterライブラリをご覧ください。

このライブラリを使用して、名前で引数を受け入れることができる関数とクラステンプレートを記述します。

 new_window("alert", _width=10, _titlebar=false);
 smart_ptr<Foo, deleter<Deallocate<Foo> >, copy_policy<DeepCopy> > p(new Foo);

名前付き引数は任意の順序で渡すことができるため、関数またはテンプレートに有用なデフォルト値を持つ複数のパラメーターがある場合に特に役立ちます。ライブラリは推定パラメータもサポートしています。つまり、そのタイプからIDを推測できるパラメーター。

于 2012-12-21T16:36:18.070 に答える
1

これが、このようなインターフェイスを避ける必要がある理由の1つです。すべてのパラメーターを含む構造を受け入れる関数のラッパーを作成します。クライアント側で、デフォルト構成をインスタンス化します(たとえば、オブジェクトコンテキストで、funcを呼び出したいときはいつでも使用できるようにします)。funcを呼び出すときはいつでも、構成を別のインスタンスにコピーし、必要な値を変更して、ラップされたfuncに渡します。

または、可能であれば、ラッパーを使用せずに関数シグネチャを直接変更して、集約された構成を受け入れることもできます。

于 2012-12-21T16:38:00.930 に答える
0

一部の引数がペアでしか意味をなさない場合は、オーバーロードされた関数を使用してください。

したがって、egの代わりに(申し訳ありませんが、今は良い例はありません)

// Adds a new TODO. Either this is a low-prio TODO with no defined 
// deadline, xor a deadlined TODO for which year, month, day must
// be passed.
void add_todo (std::string description, int year=-1, int month=-1, int day=-1);

行う

void add_todo (std::string description, int year, month, day);

void add_todo (std::string description) {
    add_todo(description, -1, -1, -1);
}

したがって、2つの可能なコールシグニチャのうちの1つだけを強制します。

もちろん、のような構造を追加する方がよいでしょうDate。しかし、それでも、それだけのために「null許容」にすることはお勧めしません。Date

void add_todo (std::string description, Date = Date::None); // <-- I wouldn't

むしろ

void add_todo (std::string description);
void add_todo (std::string description, Date deadline);

または、オーバーロードがなく、デフォルトがまったくない場合もあります

void add_todo (std::string description);
void add_deadlined_todo (std::string description, Date deadline);
于 2012-12-21T16:49:03.230 に答える
0

boost::bind(C ++ 03の場合)または(C ++ 11の場合)を使用std::bindして、関数の一部のパラメーターを並べ替えて修正できます。

于 2012-12-21T16:33:09.027 に答える