2011-11-24 11 views
8

私は、2つのデフォルトパラメータでコンストラクタを記述する必要があります。デフォルトの引数C++をスキップする方法は?

func(int arg1 , char* arg2 = "arg2", int arg3 = 1) //example 

は、私は、コンストラクタが呼び出されるシナリオを提供していますし、値はデフォルト値を使用することが予想されarg1arg2arg3に与えられています。次に、別のオブジェクトがインスタンス化され、値がarg1arg3に与えられ、arg2のデフォルト値が使用されると予想されます。 問題は、あなたが「スキップできません」というデフォルトのパラメータは、私がテキストとオンラインから読んでいることです。これは、デフォルトのパラメータを過負荷にする可能性から順序付けすることを意味しますが、シナリオにはデフォルトパラメータが使用されていますが、他のパラメータは使用されていません。この質問のヒントは、パラメータ/引数を並べ替えるよう指示します。しかし、私が行った並べ替えの量は、この問題を解決することはできないようです。

また、オーバーロードされたコンストラクタは使用できません。これは、1つのコンストラクタで行う必要があります。

どのようにこれを行うでしょうか?私は困惑し、この上でビット発狂:(

+6

これは、単一の関数定義でC++で行うことはできません。あなたが持っている奇妙な制約に違反する他のソリューションがあれば、あなたが望むのは不可能です。おそらく、あなたは別の言語を使うことができます。 –

+1

はこの宿題ですか? – xmoex

+0

'object 'の' vector'を使用できませんか?この方法で、あなたが望むものを渡し、 'ヌル 'エントリに基づいて渡されなかったものをソートすることができます。 – MoonKnight

答えて

6

また、オーバーロードされたコンストラクタはこれが1つのコンストラクタで行う必要があります。使用することはできません。

私は考えることができる唯一の理由この要件のためのオプションの引数は、同じ型を持っていることである。その場合は、あなたが立ち往生していると、あなたはnamed constructorおよび/またはnamed parameterイディオムに見たいと思うでしょう。

そうでない場合は、単に余分なコンストラクタを定義します。このデフォルト値との重複が含まれる可能性があります。

Foo(int arg1 , char const *arg2 = "arg2", int arg3 = 1) 
{ 
    construct(arg1, arg2, arg3); 
} 

Foo(int arg1, int arg3) 
{ 
    construct(arg1, "arg2", arg3); 
} 
+1

リンクを共有してくれて本当に素敵なイディオムです。スタックオーバーフローに関する素晴らしい点の1つは、スレッドをランダムに閲覧してクールなことを学べることです。+1 –

0

コンストラクタが1つだけでなければならないという特別な制限があります。非const char*に文字列リテラルからの変換は非推奨と賢明されているので、GCCと、これは警告を生成することを

#include <iostream> 

// cheap and cheerful Boost.Variant 
struct StringOrInt { 
    char *s; 
    int i; 
    bool is_string; 
    StringOrInt(char *s) : s(s), i(0), is_string(true) {} 
    StringOrInt(int i) : s(0), i(i), is_string(false) {} 
    bool isInt() { return !is_string; } 
    int asInt() { return i; } 
    char *asString() { return s; } 
}; 

struct Foo { 
    int m1; 
    char *m2; 
    int m3; 
    Foo(int arg1, StringOrInt arg2 = "arg2", int arg3 = 1) : m1(arg1) { 
     if (arg2.isInt()) { 
      arg3 = arg2.asInt(); 
      arg2 = "arg2"; 
     } 
     m2 = arg2.asString(); 
     m3 = arg3; 
    } 
    void print() { 
     std::cout << m1 << " " << m2 << " " << m3 << "\n"; 
    } 
}; 

int main() { 
    Foo(1, "HelloWorld").print(); 
    Foo(1, 2).print(); 
} 

注:ここで私が考えることができる最も近いです。しかし、あなたが求めているのは、char*のパラメータとデータメンバーがconst char*であるように修正するだけです。

重要な弱点は、これがあなたの書き込みを停止しないということです。Foo(1,2,3)コンパイル時に、複数のコンストラクタが必要だと思っているかどうかを確認する。実行時にチェックするには、別のクラスDefaultOrIntに3番目のパラメータを設定します。Defaultは、この目的にのみ使用されるタイプで、デフォルト値のarg3として使用される1つの値のみをサポートします。次に、arg2.isInt()が真の場合、arg3.isInt()は偽であり、偽でない場合はlogic_errorとなります。

0

2番目のパラメータに値がないときに空のC文字列を渡すことができる場合は、arg2をチェックし、空の場合はデフォルト値を返すヘルパーファンクタを使用できます。このような何か:

#define DEFAULT_ARG "arg2" 

struct helper_class { 
    char* operator()(char* arg) 
    { 
     if (*arg) return arg; else return DEFAULT_ARG; 
    } 
} helper; 

class func { 
    public: 
    func(int arg1 , char* arg2 = "arg2", int arg3 = 1) {} 
}; 

int main() 
{ 
    func f1(42, helper(""), 9001); // default 2nd argument 
    func f2(42, helper("Its over 9000!")); 
} 

ない私が知っている、かなり...

0

今あなたがこの種の操作を行うにはstd::bindを使用することができますまたはC++ 17分の14であなたがラムダ関数を使用して達成することができます同じ。

関連する問題