我有外部界面,让我们说20种类似的方法。每个人都可以抛出任何东西。
所以,我有20种方法:
void Call3Wrapper(int& important_parameter)
{
try
{
external_namespace::IExternal::Call3(important_parameter);
}
catch(external_namespace::Exception& ex)
{
LogIt(ex, "Call3");
throw mynamespace::MyException(ex);
}
catch(std::exception& ex)
{
LogIt(ex, "Call3");
throw mynamespace::MyException(ex);
}
catch(...)
{
LogIt("Unresolved exception", "Call3");
throw mynamespace::MyException("Unresolved exception");
}
}
每个Call1-Call20都是一样的(使用不同的参数调用)。
如:
......等等。
我对所有这些案例都有很好的函数LogIt
,我们自己的类型MyException
也可以处理所有这些案例。
所有这20个(40,60)函数体看起来都很难看,因为90%的代码都是完全相似的try-catch检查。当一个开发人员需要修复所有这些内容时,他们就会死...
是否存在一种方法/实践如何组织它不那么丑陋的方式? 像构造函数和析构函数中的lock-unlock-idiom,但是对于try-catch?
我绝对不想使用#define CALLS_CATCH_BLOCK(call_name) ...
答案 0 :(得分:1)
也许你可以模板化包装并通过函数对象调用它:
template<typename CALLABLE_T>
void CallWrapper(CALLABLE_T callable, const char* name)
{
try
{
callable();
}
catch(external_namespace::Exception& ex)
{
LogIt(ex, name);
throw mynamespace::MyException(ex);
}
catch(std::exception& ex)
{
LogIt(ex, name);
throw mynamespace::MyException(ex);
}
catch(...)
{
LogIt("Unresolved exception", name);
throw mynamespace::MyException("Unresolved exception");
}
}
然后,您可以使用std::bind
创建带参数的可调用对象,例如:
CallWrapper(std::bind(&external_namespace::IExternal::Call3,
std::ref(important_parameter)),
"Call3");
(或boost::bind
/ boost::ref
适用于较旧的编译器)
请注意,编译器仍会为每个不同的CALLABLE_T
类型生成模板的实例化,但您不需要重复代码。
另请注意,通过这种方式,您还可以调用和处理类等的成员函数。
如果要由API接口使用它,您可能仍需要创建单独的方法,但在内部调用模板化包装器而不是重复异常处理代码。