c++ - 如何在 C++ 中“退出当前函数,如果当前语句出错”
问题描述
我从一个例子开始阐述我的问题。最后以问题的确切陈述结束。
所以在C语言中,我们可以这样写一个宏,
#define NO_ERROR 0
#define RETURN_IF_ERROR(function) \
{ \
RetCode = function; \
if (RetCode != NO_ERROR) \
{ \
LOG(ERROR,"[%d] line [%d] [%s]", RetCode, __LINE__, __FILE__ ) ); \
return RetCode; \
} \
else { \
LOG(VERBOSE,"[%d] line [%d] [%s]", RetCode, __LINE__, __FILE__ ) );\
} \
}
现在这个宏可以用在这样的函数中,
int ConstructAxes() {
RETURN_IF_ERROR(GetAxis("alpha"));
RETURN_IF_ERROR(GetAxis("beta"));
RETURN_IF_ERROR(GetAxis("gamma"));
RETURN_IF_ERROR(GetAxis("delta"));
.
.
.
}
因此,我们立即退出当前函数(例如 ConstructAxes)并返回错误代码,如果其中调用的函数之一返回错误。如果没有那个宏,对于这 4 个语句中的每一个,我都必须编写一个 if...else 块。我最终会得到 4 行显示实际功能或任务的代码,然后是另外 16 行错误检查(和/或可选的日志记录)。(我见过 700 多行长的函数,只有 20~30 行功能和 600 多行 if...else 错误检查和日志记录。不太容易遵循主要逻辑。)
(在有人指出之前,我不能使用异常。这是一个遗留项目,不使用也不希望使用异常,我也不是编写异常安全代码的专家。同样在有人指出之前,返回的错误代码在更高层次上被重新解释为一些有意义的文本。在哪里以及如何与手头的这个问题无关。)
问题是,宏可能有问题,我更喜欢函数。那么在 C++ 中是否有一些简洁优雅的方法可以在不使用宏的情况下做到这一点?我有一种感觉,这是不可能的。
解决方案
好的,对于嵌入式设备,您可能需要避免任何可能需要内存分配的复杂 C++ 好东西。但是我会拆分必须始终发生的日志记录部分和块短退出。
int test_and_log(int RetCode) {
if (RetCode != NO_ERROR)
{
LOG(ERROR,"[%d] line [%d] [%s]", RetCode, __LINE__, __FILE__ ) );
}
else {
LOG(VERBOSE,"[%d] line [%d] [%s]", RetCode, __LINE__, __FILE__ ) );
}
return RetCode;
}
然后是一个极简宏(C方式):
#define RETURN_IF_ERROR(x) { int cr; if ((cr = test_and_log(x)) != NO_ERROR) return cr; }
int ConstructAxes() {
RETURN_IF_ERROR(GetAxis("beta"));
RETURN_IF_ERROR(GetAxis("gamma"));
RETURN_IF_ERROR(GetAxis("delta"));
.
.
.
return 0; // ensure a return value if every line passes
}
但是对于 C++,我仍然会通过抛出一个 int 值来使用极简的异常处理:
void test_and_log(int RetCode) {
if (RetCode != NO_ERROR)
{
LOG(ERROR,"[%d] line [%d] [%s]", RetCode, __LINE__, __FILE__ ) );
throw RetCode;
}
else {
LOG(VERBOSE,"[%d] line [%d] [%s]", RetCode, __LINE__, __FILE__ ) );
}
}
接着:
int ConstructAxes() {
try {
test_and_log(GetAxis("beta"));
test_and_log(GetAxis("gamma"));
test_and_log(GetAxis("delta"));
.
.
.
}
catch (int RetCode) {
return RetCode;
}
return 0; // ensure a return value if every line passes
}
这相当 hacky,因为最佳实践建议只抛出 的子类std::exception
以进行一致的异常处理。但是正如您所说,您不想在应用程序中使用异常,这是可以接受的。嵌入式系统的优点是不会构造普通的异常对象。但请不要在普通代码中使用它。
如果你想用内存来换取处理时间,你总是可以test_and_log
用inline
说明符声明......
推荐阅读
- javascript - 从对象数组中获取对象数组内的数组 - 到新的对象数组
- python - 条形图崩溃(?)和数据重叠
- dictionary - 在 Flutter 中创建列表映射
- ibm-integration-bus - IBM Integration Bus 中超时通知节点的替代方案
- python - 如何在 Python 中计算平均偏差误差(MBE)?
- android-layout - CollapsingToolbarLayout 的toolbarId 属性有什么用?
- dropzone.js - Dropzone多文件上传一次上传2个文件
- java - 如何将值转换为字符串?
- javascript - 为什么我的游戏没有运行并且某些元素没有加载?
- ios - 在实体上添加两个核心数据派生属性会导致在向该实体添加对象时崩溃