我有一系列非常相似的成员函数,我想我可以通过模板或其他方法使代码更易于维护,但我不知道该怎么做。
以下是我的一个功能示例:
void CalController::bgc_cmd(const std::string& s) {
try {
this->cohort_ptr->md->set_bgcmodule(temutil::onoffstr2bool(s));
LOG(note) << "CalController turned bgc module to "
<< s <<" via cohort pointer...";
} catch (const std::runtime_error& e) {
LOG(warn) << e.what();
}
}
我的其他功能完全相同,除了:
bgc_cmd(..)
,env_cmd(..)
,dsl_cmd(..)
md
块中调用的try...catch
类的成员函数基本上,我希望避免在每个try..catch
函数中复制LOG(..)
阻止和CalController::XXX_cmd(...)
消息。
使用boost::function
和/或boost::bind
会很好,我只是围成一圈,无法弄清楚如何设置它。
答案 0 :(得分:2)
你可以写一个成员函数来做所有这些事情。没有必要bind
或模板,因为md
上的所有内容都是一个采用相同参数类型的函数。我将使用MD
作为md
的类型,我假设onoffstr2bool
返回bool
:
void set_cmd(void (MD::*fn)(bool), const std::string& name, const std::string& s)
{
try {
(this->cohort_ptr->md->*fn)(temutil::onoffstr2bool(s));
LOG(note) << "CalController turned " << name << " to "
<< s <<" via cohort pointer...";
} catch (const std::runtime_error& e) {
LOG(warn) << e.what();
}
}
然后你会称之为:
void CalController::bgc_cmd(const std::string& s) {
set_cmd(&MD::set_bgcmodule, "bgc module", s);
}
答案 1 :(得分:1)
我认为你可以通过一个简单的常规功能得到你想要的东西。无需模板:
void CalController::do_cmd(boost::function<void (String)> fun, const std::string& s) {
try {
fun(temutil::onoffstr2bool(s));
LOG(note) << "CalController turned bgc module to "
<< s <<" via cohort pointer...";
} catch (const std::runtime_error& e) {
LOG(warn) << e.what();
}
}
然后你可以使你的其他方法类似:
void CalController::bgc_cmd(const std::string& s) {
// here TypeOfMd is whatever the type is for this->cohort_ptr->md.
// This binds the "this pointer" for set_bgcmodule to this->cohort_ptr->md
do_cmd(boost::bind(&TypeOfMd::set_bgcmodule, this->chort_prt->md), s);
}
这里需要注意的一些事项:
答案 2 :(得分:1)
如果使用C ++ 11,您可以使用更通用的名称创建一个函数,让我们说exex_cmd
。
然后,您可以将lambda函数作为参数传递,并在try / catch块中执行它 - 无需使用模板。
//WARNING: Untested code - the point is that you get the idea. Modify at will.
void CalController::exec_cmd(const std::function<void (void)> func) {
try {
//Invoke lambda.
//The string is passed via closure implementation,
//but you can always pass it as normal argument if you want.
func();
LOG(note) << "CalController turned bgc module to "
<< s <<" via cohort pointer...";
} catch (const std::runtime_error& e) {
LOG(warn) << e.what();
}
}
然后,创建3个包装器方法,调用exec_cmd
,但传递一个不同的lambda作为参数:
void CalcController::bgc_cmd(const std::string& s){
CalcController::exec_cmd([=] () {
//Taking closures into control, to avoid passing the string as argument.
this->cohort_ptr->md->set_bgcmodule(temutil::onoffstr2bool(s));
})
}
void CalcController::env_cmd(const std::string& s){
CalcController::exec_cmd([=] () {
//different function invocation here.
})
}
同样,你可以为你的所有功能做到这一点。
您可以查看here了解有关C ++ 11的lambda的更多信息。
普通C ++中的类似方法是定义函数指针类型并将函数指针传递给exec_cmd
,在类型签名后创建正常函数并将它们作为参数传递,或传递成员函数指针 - 你可以看看巴里的答案。