2011-11-24 522 views
8

我必須寫兩個默認參數的構造函數。如何跳過默認參數C++?

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

我提供在構造函數被調用的場景和值是給arg1arg2arg3預計將使用默認值。然後另一個對象被實例化並且給定值爲arg1arg3,並且預期將使用arg2的默認值。 現在的問題是,你「無法跳過」默認參數是我正在從文本和在線閱讀。它的意思是命令默認的參數從超負荷的角度來看,但是場景有一個默認參數,而另一個參數不是。這個問題的提示告訴我重新排序參數/參數。但是,我所做的重新排序量似乎無法解決此問題。

此外,重載的構造函數不能使用。這必須由一個構造函數完成。

那麼如何做到這一點?我難倒和去有點瘋狂了這個:(

+6

您不能在C++中使用單個函數定義來完成此操作。鑑於任何其他解決方案違反了你所擁有的奇怪限制,你想要的是不可能的。也許你可以使用不同的語言。 –

+1

正在做作業嗎? – xmoex

+0

你不能使用對象的'vector'嗎?這樣你就可以傳遞你想要的東西,並根據'null'條目對沒有傳遞的東西進行排序。 – MoonKnight

回答

6

而且,重載的構造函數不能使用。這必須通過一個構造函數來完成。

我能想到的唯一原因這個要求是可選的參數具有相同的類型。在這種情況下,你就完蛋了,你會想看看到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 –

0

特殊的限制,只能有一個構造函數。這是我能想到的最接近的:

#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(); 
} 

注意與GCC這會產生警告,因爲從一個字符串到非const char*轉換已被棄用,不明智的。但這是你要求的,並修復它,以便char*參數和數據成員是const char*很容易。

一個顯着的弱點是,這並不能阻止你寫Foo(1,2,3)。要在編譯時檢查,我認爲你需要多個構造函數。要在運行時檢查它,可以將第三個參數設置爲另一個類,其中Default是僅用於此目的的類型,僅支持一個用作arg3的默認值的值。那麼,如果arg2.isInt()爲真,則檢查arg3.isInt()是否爲假,如果不是則拒絕logic_error

0

如果您在第二個參數沒有值的情況下允許傳遞空的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++十七分之十四你可以使用lambda函數,完成一樣。