0

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

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 函数之前成员变量未设置为空,它仍然很丑陋,并且具有不让这些值之一真正为“空”的缺点。它还强制检查类的人检查方法的实现,以了解将使用成员默认值而不是空值。

我确定有一种方法、一种模式或其他东西可以使这件事变得正确,但我还没有找到它:(

谢谢你的帮助!

4

2 回答 2

0

不是答案,而是我可以明智地粘贴代码的唯一方法。下面是如何执行代码部分的示例,以便一个 init 将处理您想要的,但是参数必须按照您为函数定义声明的顺序,但是您可以使用 one base 添加简单的重载以一些简单和最小化的方式运行和维护功能:

注意:下面的代码不适用于重载,因为我在 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;
}
于 2013-10-29T16:46:26.413 回答
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
}

请注意,我故意做出了一些设计决定,此代码不打算按原样使用。一方面,它不处理参考参数。

你可以在这里玩代码。

于 2013-10-29T16:46:27.113 回答