结合基于异常和错误代码的类实现 我正在编写一个C++类,它有两种不同的使用模型。一种是外部的,我们假设用户不希望引发任何异常。而是返回错误代码。 另一种使用方式是内部的,我努力避免繁琐的错误代码检查,更喜欢处理异常

结合基于异常和错误代码的类实现 我正在编写一个C++类,它有两种不同的使用模型。一种是外部的,我们假设用户不希望引发任何异常。而是返回错误代码。 另一种使用方式是内部的,我努力避免繁琐的错误代码检查,更喜欢处理异常,c++,exception,interface,C++,Exception,Interface,将这两种方法结合起来的好方法是什么 编辑: 这两种方法可以在同一个二进制文件中使用 显性比隐性好 避免向用户公开特殊构造 创建类的两个版本,一个抛出错误代码,另一个返回错误代码。它们都可以从一个包含大部分代码的公共基派生出来。从未尝试过这样的事情,但我会这么做 错误类型: extern const bool exceptionmode; enum error_codes {no_error, whatever}; struct error_type { error_codes id;

将这两种方法结合起来的好方法是什么

编辑:

  • 这两种方法可以在同一个二进制文件中使用
  • 显性比隐性好
  • 避免向用户公开特殊构造

创建类的两个版本,一个抛出错误代码,另一个返回错误代码。它们都可以从一个包含大部分代码的公共基派生出来。

从未尝试过这样的事情,但我会这么做

错误类型:

extern const bool exceptionmode;

enum error_codes {no_error, whatever};
struct error_type {
    error_codes id;
    //maybe also a non-owning const char* message?

    error_type() :id(no_error) {}
    error_type(error_codes code) :id(code) 
    {
        if (exceptionmode) throw_as_exception();
    }

    const char* get_as_string() {
        switch(id) {
        case whatever: return "out of bounds exception";
        case no_error: return "no error";
        default: return "unknown exception";
        }
    }
    void throw_as_exception() {
        switch(id) {
        case whatever: throw std::out_of_bounds("out of bounds exception");
        case no_error: break; //no error
        default: throw std::exception("unknown exception");
        }
    }

};
类别和功能:

class myclass {
public:        
    error_type my_member_function() {
         //stuff
         if (condition)
             return whatever;
         //more stuff
         return no_error;
    }
};

如果你真的有勇气,你可以这样做,这样错误类型的类就不会被比较、转换或检查,以确保没有人忘记检查返回值。

我更喜欢Mark Ransom的答案,除非由于其他原因创建两个类是不可行的

或者,您可以创建接口,以便每个函数都有一个带有默认值的最终参数,例如int*pRet=NULL。如果pRet==NULL,则指示使用异常。如果是pRet!=NULL,则调用方已传入一个指针,该指针应在函数末尾使用错误代码进行更新


在函数内部,您需要捕获异常,然后根据pRet参数吞掉它们或重新抛出它们。

我考虑过了。1.为此维护3个类不是太麻烦了吗。我有不止一个班级需要这种治疗。2.两门课不够吗?其中一个将作为另一个的门面,并将其异常转换为错误代码。@Albert,是的,您可以使用两个类。我只是觉得用三个类会更简洁。@Albert您甚至可以用一个类来完成,并为每个函数提供两个不同的版本,一个抛出,一个不抛出。这看起来更难看,但如果外部程序有时将对象传递回库中,它可能会更好。我认为两个类会更干净。用户不太容易出错(抛出函数的界面更易于使用)。如果一个外部程序将传回这些对象,那么我将通过cast或其他方式公开抛出接口。如果只有一些函数是这样的,我会选择这种方法。类似于
std::vector
at
[]
访问器。所说的
不使用异常
是指(1)它们不允许作为语言构造,因为RTTI被禁用,还是(2)用户只是不想在代码中看到它们?(2) 也会影响你的“内部”代码。没错,当从公共成员函数中使用时,内部代码总是在
try catch
块中。如果使用2个类和facade之类的东西,则需要确保基类型和派生类型之间永远不会发生转换。您不能将这些函数设置为虚拟函数,因为返回类型不会是共变量。我要上3节课。这将仍然是繁琐的,因为<代码>抛出点可以在函数的中间,并且不能高效地重用代码,但这就是你得到的。@ PMR,我指的是2个类和组成,而不是继承。<代码> Extn const BOOL异常模式;<代码>太全局化了。这两种方法可以在同一个二进制文件中使用。但是,我可以在类构造函数(或模板参数)中提供这个布尔参数,并使用工厂(或模板)生成错误代码。与隐式转换相比,我更喜欢显式工厂方法调用。它更清晰,用户不需要知道任何特殊的类。只是一个枚举或整数。我不喜欢这种方法,因为它总是返回一些东西,即使在异常模式下也是如此。是的,它总是返回一些东西,但在exceptionmode中,它总是返回
no\u error
,因此可以忽略。