2013-10-29 42 views
0

我试图找到一个优雅的方式来声明一个启动函数,它使用当前存储在我的对象(非静态值)中的默认值。我基本上喜欢做这样的事情。多个非静态默认参数C++

class A{ 
    A([...], 
     string defaultName, 
     vector<string> defaultUrls, 
     map<string, string> defaultParams); 

    [...] 

    void initSomething(string defaultName = mDefaultName, 
        vector<string> defaultUrls = mDefaultUrls , 
        map<string, string> defaultParams =mDefaultParams); 

    private: 
    string mDefaultName; 
    vector<string> mDefaultUrls; 
    map<string, string> mDefaultParams; 
    [...] 
} 

我知道我可以重载initSomething()功能,但我会得到这样的:

void initSomething(){ 
    initSomething(mDefaultName, mDefaultUrls, mDefaultParams); 
} 

void initSomething(string defaultName){ 
    initSomething(defaultName, mDefaultUrls, mDefaultParams); 
} 

void initSomething(vector<string> defaultUrls = mDefaultUrls){ 
    initSomething(mDefaultName, mDefaultUrls, mDefaultParams); 
} 

void initSomething(map<string, string> defaultParams){ 
    initSomething(mDefaultName, mDefaultUrls, defaultParams); 
} 

void initSomething(string defaultName, vector<string> defaultUrls){ 
    initSomething(mDefaultName, mDefaultUrls, mDefaultParams); 
} 

void initSomething(string defaultName, map<string, string> defaultParams){ 
    initSomething(defaultName, mDefaultUrls, defaultParams); 
} 

void initSomething(vector<string> defaultUrls, map<string, string> defaultParams){ 
    initSomething(mDefaultName, defaultUrls, defaultParams); 
} 

void initSomething(string defaultName, 
       vector<string> defaultUrls, 
       map<string, string> defaultParams); 

这实在是太丑陋,如此庞大的它使整个头文件难以阅读和领悟其中奥妙的。

我也想过别的东西:

void initSomething(string defaultName = "", 
       vector<string> defaultUrls = vector<string>(), 
       map<string, string> defaultParams = map<string, string>()){ 
    if (defaultName == "") { 
     defaultName = mDefaultName; 
    } 

    if (defaultUrls.empty()) { 
     defaultUrls = mDefaultUrls; 
    } 

    if (defaultParams.empty()) { 
     defaultParams = mDefaultParams; 
    } 

    [...] 
} 

它仍然是丑陋,也没有让这些值中的一个真正是“空”,如果成员变量未设置为空调用initSomething之前的缺点功能。它还会强制某人检查该类以检查方法的实现,以了解将使用成员默认值而不是空值。

我敢肯定有一种方法,图案或东西,使这个正确的,但我还没有找到它:(

感谢您帮助!

+0

这是一个严格的pre-C++ 11问题吗? –

+0

哦,我还没有用过C++ 11,而且自从修改了pre-C++ 11以后,我会说找到一种方法可以在不使用C++ 11特性的情况下进行更改。我会阅读这个功能,如何,thx! –

+0

有这样做的方法,你猜,我可能会倾向于最基本的版本,你有一个简单的标题条目'void initSomething(string defaultName = NULL,vector defaultUrls = NULL,map defaultParams = NULL)'并在cpp文件中有一些逻辑来处理存在的参数。不优雅,但简单而有效。 – GMasucci

回答

0

这是我想到的最好的。希望能帮助到你。

#include <vector> 
#include <string> 
#include <iostream> 

struct A{ 
    struct Default {}; 
    template <typename T> 
    struct Parm{ 
     Parm() : gotHam(false), ham() {}; 
     Parm(const Default&) : gotHam(false), ham() {} 
     Parm(const T& ham_) : gotHam(true), ham(ham_) {} 
     operator bool(){ 
      return gotHam; 
     } 
     const bool gotHam; 
     T ham; 
    }; 
    A(std::string s_) : s(s_), i(5) {} 

    void myFunction(Parm<std::string> s_ = Parm<std::string>(), Parm<int> i_ = Parm<int>()){ 
     std::string sValue = s_?s_.ham:s; 
     int iValue = i_?i_.ham:i; 
     std::cout << sValue << '\t' << iValue << std::endl; 
    } 

    std::string s; 
    int i; 
}; 

int main() { 
    A a("defaulted"); 

    a.myFunction(std::string("caller provided")); //caller provided 5 
    a.myFunction(A::Default()); //defaulted 5 
    a.myFunction(); //defaulted 5 

    a.myFunction(std::string("caller provided"), 10); //caller provided 10 
    a.myFunction(A::Default(), 10); //defaulted 10 
} 

请注意,我故意做出了一些设计决定,但此代码并不打算按照原样使用。首先,它不处理参考参数。你可以玩代码here

0

不是一个答案,但唯一的办法我可以合理地粘贴代码 以下是如何执行代码部分的示例,以便一个init可以处理您想要的内容,但参数必须按照您为函数的定义指定的顺序进行操作,不过您可以使用一个基本功能添加简单的过载,并通过一些简单和最小的烦恼来维护功能:

注意:下面的代码不能用于重载,因为我已经在if语句中使用了整型返回和参数,所以结果不会有任何区别,但它可以用来说明原理。

#include <iostream> 
#include <map> 
#include <stdlib.h> 
#include <sstream> 
#include <vector> 


using namespace std; 
// this one can be private, or leave it public for versatility 
int initSomething(string defaultName = "", vector<string> defaultUrls = vector<string>() , map<string, string> defaultParams = map<string, string>()) 
{ 
    int mDefaultName, mDefaultUrls, mDefaultParams = 0; 
    if (defaultName == "") 
     { 
      // set your default value here 
      mDefaultName = 1; 
     } 
    if (defaultUrls == vector<string>()) 
     { 
      // and here 
      mDefaultUrls = 2; 
     } 
    if (defaultParams == map<string, string>()) 
     { 
      // and finally here 
      mDefaultParams = 3; 
     } 

    // and here you can do whatever you want to do, 
    // and regardless of what form you call the one init will handle all the eventualities 
    return mDefaultName + mDefaultUrls +mDefaultParams; 
} 
// variants 
// these can be public 
int initSomething()              {initSomething("", vector<string>() ,map<string, string>());} 
int initSomething(map<string, string>mystringmap)      {initSomething("", vector<string>() ,mystringmap);} 
int initSomething(vector<string> myvector)        {initSomething("", myvector ,map<string, string>());} 
int initSomething(vector<string> myvector, string>mystringmap)   {initSomething("", myvector ,mystringmap);} 
int initSomething(string mystring)          {initSomething(mystring, vector<string>() ,map<string, string>());} 
int initSomething(string mystring, vector<string> myvector)    {initSomething(mystring, myvector ,map<string, string>());} 
int initSomething(string mystring, map<string, string>mystringmap)  {initSomething(mystring, vector<string>() ,mystringmap);} 
// and so on 
int main() 
{ 
    cout << initSomething() << endl; 
    return 0; 
}