多个非静态默认参数c ++

时间:2013-10-29 15:20:45

标签: 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函数之前,成员变量未设置为空,则不能让其中一个值真正为“空”。它还强制某人检查类以检查方法的实现,以了解将使用成员默认值而不是空值。

我确信有一种方法,一种模式或其他方法可以做到这一点,但我还没有找到它:(

谢谢你的帮助!

2 个答案:

答案 0 :(得分: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;
}

答案 1 :(得分: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