我的C ++函数有许多if语句检查被调用函数的返回值:
Result func(...){
if (SUCCESS != func1(...))
return ERROR;
// do something
if ( SUCCESS != func2(...))
return ERROR;
// do something else
if (SUCCESS != func3(...))
return ERROR;
// do something
.
.
.
}
是否有消除或减少if语句? 例如,我想要这样的东西:
Result func(...){
Result result = SUCCESS;
when (result != SUCCESS) return ERROR;
result = func1(...);
// do something
result = func2(...);
// do something else
result = func3(...);
// do something
.
.
.
}
答案 0 :(得分:3)
我无法帮助自己,但编写可能被视为过度工程的解决方案,但它允许为所有结果准备单个模板类(供将来使用),然后最小化代码以供实际使用(无需使用检查方法或者宏,除了这个单独的结果持有者模板类之外,不需要编写自己的包装器)。享受:D。
#include <iostream>
template<class T>
class Result
{
public:
Result() :
m_value(),
m_badValue()
{
}
Result(const T& value, const T& badValue) :
m_value(value),
m_badValue(badValue)
{
}
void operator=(const T& value)
{
if(value == m_badValue)
{
throw "Bad Value!";
}
else
{
m_value = value;
}
}
operator const T&() const
{
return m_value;
}
const T& value() const
{
return m_value;
}
private:
T m_value;
T m_badValue;
};
static const int SUCCESS = 0;
static const int FAIL = -1;
int func1()
{
return SUCCESS;
}
int func2()
{
return SUCCESS;
}
int func3()
{
return FAIL;
}
int main()
{
Result<int> result(FAIL, FAIL);
try
{
result = func1();
result = func2();
result = func3();
}
catch (const char *error)
{
::std::cout << "Error: " << error << ::std::endl;
}
::std::cout << "Last value: " << static_cast<int>(result) << " - " <<
((result == SUCCESS) ? "SUCCESS" : "FAIL") << ::std::endl;
}
注意:你应该只抛出::std::exception
派生的内容,但我使用const char*
来简化事情并准备工作示例。
答案 1 :(得分:2)
简答:没有
答案很长:不,那就是你在我所知道的每种结构化编程语言中都是这样做的。
替代方案:如果涉及的所有功能(func1
,func2
,func3
)都会抛出异常而不是返回状态代码,那么您就不必使用ifs。您的函数func
只会传播从其中抛出的任何异常。
编辑,扩展Tony的评论:
备选方案#2:涉及的函数不会抛出异常,但是你的函数可以。假设你有一个这样的辅助函数:
void CheckResult(Result result)
{
if (result != SUCCESS)
throw SomeException(result);
}
您的功能将如下所示:
void func(...)
{
CheckResult(func1(...));
// do something
CheckResult(func2(...));
// do something else
CheckResult(func3(...));
// do something
}
因此,if
不会被避免,而是转移到另一个函数,这样你的函数就没有了。
答案 2 :(得分:2)
由于您使用C ++进行编码,而不是使用C编写,因此可以使用抛出异常的选项。使代码看起来更好,同时适当地响应异常情况是该功能背后的主要驱动力。
在使用不提供异常的第三方API的情况下,您可以将其函数包装到抛出异常的函数中,如下所示:
void func1w(...) {
if (SUCCESS!=func1(...)) throw my_exception();
}
void func2w(...) {
if (SUCCESS!=func2(...)) throw my_exception();
}
...
void caller() {
try {
func1w();
func2w();
func3w();
} catch (my_exception& e) {
cerr << "Error!" << endl;
}
}
请注意,调用异常抛出包装器的函数可能远离完全检查异常代码,让更高级别的函数处理它们。有例外的一般规则是代码不应该捕获异常,除非它知道如何处理它们。
您还可以定义宏:
#define MUST_SUCCEED(x) if(SUCCESS!=(x))return ERROR
这是以降低可读性为代价的,因为您的代码的读者不会立即熟悉该宏:
MUST_SUCCEED(func1(...));
MUST_SUCCEED(func2(...));
MUST_SUCCEED(func3(...));
答案 3 :(得分:0)
你可以创建一个包含func1(),func2()等函数指针的向量,然后通过for循环遍历这个向量中的所有元素,调用每个函数并比较返回的值与SUCCESS。然后,如果任何函数的返回值不等于SUCCESS,则可以将标志设置为指示错误的值(在您的示例中,此标志将是名称&#39; result&#39;)。