同じことをする異なる関数シグネチャを提供することは良い考えですか?


23

以下は、3つの値で構成されるC ++クラスです。

class Foo{

    //Constructor
    Foo(std::string, int, char);

private:
    std::string foo;
    char bar;
    int baz;
};

すべてのパラメータータイプは異なります。
順序が問題にならないように、コンストラクタをオーバーロードできます。

class Foo{

    //Constructors
    Foo(std::string, char, int);
    Foo(std::string, int, char);
    Foo(char, int, std::string);
    Foo(char, std::string, int);
    Foo(int, std::string, char);
    Foo(int, char, std::string);


private:
    std::string foo;
    char bar;
    int baz;
};

しかし、それは良い考えですか?
クラス/関数に必要なものがわかっていたので、それを始めました。
私はそれがそれらをどの順序で取ったかをいつも覚えていませんでした。


私は、コンパイラーが同じコンストラクターを呼び出したかのように、コンパイラーがこれを最適化すると仮定してきました。

//compiler will implement this with the same code? 
//maybe not.. I could call a function to get a parameter, 
//and that function could change the state of the program, before calling
//a function to get another parameter and the compiler would have to
//implement both
Foo foo1("hello",1,'a');
Foo foo2('z',0,"world");

順序が関係ないように関数をオーバーロードすることについて、あなたの意見は何ですか?


また、いくつかのユーティリティ関数を書いている場合
、同じことをする異なる関数名を提供することは良い考えですか?

例えば。

void Do_Foo();
void DoFoo();
void do_foo();
//etc..

私はこれらの2つの類似した規則を頻繁に見ません。
習慣を破るか、受け入れるべきですか?


1
明示的に指定された各方法が他の方法よりも明確かつ明確に優れている場合、何かを表現するための複数の方法を提供する努力のみを費やすべきです。だからといって、一般に1つの正規形でしか書けないように努力する必要があるという意味ではありませんが、最善ではない何らかの方法で何かを指定できるように努力することは意味がありません。
supercat

ここでの私の質問の複製の一種(これは悪い考えだと今同意します)。
左周り

回答:


93

[パラメーターの]順序が問題にならないように、コンストラクターをオーバーロードすることもできます...しかし、それは良い考えですか?

いや

異なるコンストラクタのオーバーロードを使用すると、意図するものと逆の効果があります。異なるオーバーロードが異なる動作をすることを期待した後に来るプログラマーは、「これらのオーバーロードのそれぞれによってどのような異なる動作が表現されているのか?」と尋ねます。

ほとんどのプログラマーは、事前定義された順序でメソッドパラメーターを使用するという規律を期待しており、IntelliSenseなどのツールは、パラメーターを入力するときにパラメーターの予想される順序を通知します。


同じことをする複数の関数名を持つことは同じ問題です。プログラマは、バリアントの動作が異なることを期待しています。動作ごとに1つの関数またはメソッドを使用し、一貫した命名パターンを採用してください。


14
たくさんの賛成票。すぐに停止します。ありがとうございました。
トレバーヒッキー

8
さらに、目的を説明するためにコンストラクタに異なる名前を付けることはできません。読者は、パラメータからコンストラクタを推測する必要があります。この方法でコンストラクターをオーバーロードすると、理解しにくくなります。
ザカリーイェーツ

3
「同じことをする複数の関数名を持っている...」-しばらくの間、RubyのクラスString Hash Array Fileを見てください

+1。開発者/プログラマーを扱っています。「ユーザーは猿」というマイクロソフトの考えは、ここでは機能しません。
マノジR

1
@ZacharyYates代わりに静的な構築メソッドを公開することで、「コンストラクター名」の不足を回避できます。これはJavaの標準的な慣行ですが、C ++ではそれほどではありません。
シオン

14

引数間の交換をサポートすることが必要な場合があります。例えば:

double operator *(int, double);
double operator *(double, int);

オペランドが逆になった場合、anの乗算intdouble異なる計算は必要ありません。また、intsとを乗算するとき、左側に行くことをプログラマに思い出させる必要もありません!doublesdouble

同じことが次の理由で当てはまるため、これが演算子であることは関係ありません。

footype plus(const footype &, const bartype &);
footype plus(const bartype &, const footype &);

それは本当に機能の種類に依存します。ほとんどのプログラマーはおそらく算術ライブラリーの可換性のサポートを望んでいますが、たとえば、可能なすべての引数の順序をサポートするためのI / Oライブラリー関数は必ずしも必要ではありません。

この懸念は、おそらく関数呼び出しが関与する予定のネストにかかっています。算術演算子の柔軟性により、構文ツリーの全体構造を変更して、全体の表現を明確にすることができます。類似した用語などをグループ化します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.