如果构造函数中有错误,请停止进程

罗伯特·特鲁德尔

在实用程序类文件中,我想打开一个文件以进行读取或写入。
如果无法打开它,我不想继续该过程。

FileUtility::FileUtility(const char *fileName) {
  ifstream in_stream;
  in_stream.open(filename);
}

FileUtility fu = FileUtility("bob.txt");
fu.read();
fu.write();

文件bob.txt不存在,所以我不想读取和写入方法。

有没有一种干净的方法可以做到这一点?

bgoldst

通常,有四种方法可以将错误状态从被呼叫者传达给呼叫者:

1.直接返回值(返回码或OUT参数)。

尽管可以使用OUT参数,但对于构​​造函数调用而言,返回码是不可能的。但是,为此目的要求每个函数提供其返回代码或OUT参数在某种程度上具有侵入性,因此,尽管肯定在各种库和API中大量使用了此解决方案,但我总体上并不喜欢该解决方案。您可以通过向构造函数添加指针或引用参数来使用此方法,调用者可以向该指针或引用参数提供一些局部错误变量的地址,构造函数可以在其中存储可能的返回值。我不建议这样做。

2.例外。

在C ++代码和其他语言中,关于异常的优缺点的争论有些两极化。我可能会这样说,但我个人认为应该避免像瘟疫一样避免例外。访问http://www.joelonsoftware.com/items/2003/10/13.html,以了解支持我观点的人。但是,如果您愿意的话,这是一个可行的解决方案。有关此解决方案的良好演示,请参见@Br​​ian的答案。

3.对象属性。

std::ifstream对象实际上是这样做的,因此您可以利用它。(实际上,从您的示例代码中,您将您定义std::ifstream为构造函数中的局部变量,这意味着该变量在调用后将不会持久化,但是由于您在构造对象上调用了某种read()write()方法,这意味着您确实可以持久调用之后,因此我将假设后者是正确的推断。)您可以通过调用来利用它std::ifstream::is_open()如果您要维护的封装,则std::ifstream可以定义自己的is_open()等效项,并假设它保留为类的一个属性FileUtility,则将in_stream.is_open();再次简单地返回FileUtility

struct FileUtility {
    ifstream ifs;
    FileUtility(const char* fileName);
    bool is_open(void) const;
};

FileUtility::FileUtility(const char* fileName) { ifs.open(fileName); }
bool FileUtility::is_open(void) const { return ifs.is_open(); }

FileUtility fu = FileUtility("bob.txt");
if (!fu.is_open()) return 1;

或者,您可以仅为FileUtility该类创建一个全新的错误状态层,然后std::ifstream通过该传播错误。例如:

struct FileUtility {
    static const int ERROR_NONE = 0;
    static const int ERROR_BADFILE = 1;
    ifstream ifs;
    int error;
    FileUtility(const char* fileName);
};

FileUtility::FileUtility(const char* fileName) : error(ERROR_NONE) {
    ifs.open(fileName);
    if (!ifs.is_open()) { error = ERROR_BADFILE; return; }
}

FileUtility fu = FileUtility("bob.txt");
if (fu.error != FileUtility::ERROR_NONE) return 1;

这些是合理的解决方案。

4.全局错误状态。

如果某些程序员对这种可能的解决方案做出“听起来像个坏主意”的反应,我不会感到惊讶,但事实是,许多非常成功且杰出的代码库都使用这种解决方案来传达错误状态。最好的例子也许是errnoC标准库使用变量(尽管应该指出,errno这种工作与直接返回代码结合使用)以及GetLastError()Windows C API使用系统。我想有些人可能会认为这确实是“ C方法”,而例外就是“ C ++方法”,但是同样,我避免了像瘟疫这样的例外。

顺便说一句,multithreadedness是不是该解决的问题,因为errnoGetLastError()这两个线程局部错误状态,而不是真正的全局错误状态。

我最喜欢此解决方案,因为它简单,极具侵略性,并且可以轻松地被不同的代码库重用,当然,前提是您可以ERROR_NONE在它自己的库,在这种情况下,您的代码在错误处理方面会获得一致性。

例子:

#define ERROR_NONE 0
thread_local int error = ERROR_NONE;

struct FileUtility {
    static const int ERROR_BADFILE = 1;
    ifstream ifs;
    FileUtility(const char* fileName);
};

FileUtility::FileUtility(const char* fileName) {
    ifs.open(fileName);
    if (!ifs.is_open()) { error = ERROR_BADFILE; return; }
}

FileUtility fu = FileUtility("bob.txt");
if (error != ERROR_NONE) return 1;

这是我建议的解决方案。否则,我将使用对象属性解决方案。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

如果页面中有错误,请重定向到自定义错误页面

如果不起作用,请让函数进入内部。(没有错误信息)

如果验证中有任何错误,请禁用“提交”按钮

没有默认的构造函数并且没有错误

我在joomla中有一个错误-请查询。我在这个查询中有错误

没有错误:未调用PDO构造函数

如果有错误并打印错误消息,请不要执行

如果超构造函数中有参数,则超类内部类的构造函数未定义

我在 mysql 函数中有错误?ERROR 不允许从函数返回结果集

如果我们在CloudFormation中有错误条件和Ref会发生什么?

如果命令中有错误,如何制作批处理文件报告

SQLException SQL语法中有错误

parseInt行中有错误

我的查询中有错误

我在时区设置中有错误

@Query,存储库中有错误

函数中有错误91,但类似子中没有

Robocopy Monitor进程在计划的任务中运行,随机停止,没有错误

如果出现服务器错误,如何停止带有错误消息的微调器

R中有错误的单纯形函数的基本示例

如果任何脚本有错误,如何停止运行多个python脚本

带有构造函数和函数的类中有很多错误

如果有错误,请执行此操作并返回,否则继续在一行中执行

如果pom.xml文件中有错误,则在创建Maven项目时可能会出错

您的 SQL 语法错误中有错误吗?

如果没有错误,则返回Golang

PowerShell Azure 函数在没有错误消息的情况下执行时停止

如果没有错误,node.js回调函数是否需要null?

如果没有错误,为什么 GL 函数调用返回的位置为 -1?