我正在尝试找到一种优雅的方式来声明一个启动函数,该函数使用当前存储在我的对象中的默认值(非静态值)。我基本上想做这样的事情。
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 函数之前成员变量未设置为空,则不会让其中一个值真正"空"。它还强制检查类的人检查方法的实现,以了解将使用成员默认值而不是空值。
我确信有一种方法,一种模式或其他东西可以做到这一点,但我还没有找到它:(
感谢您的帮助!
这是我想到的最好的。希望对您有所帮助。
#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
}
请注意,我故意做出了一些设计决策,此代码不打算按原样使用。首先,它不处理引用参数。
您可以在此处使用代码。
答案,而是我能明智地粘贴代码的唯一方法。下面是一个如何执行代码部分的示例,以便 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;
}