接口(抽象类)设计的最佳方法

Best approach to interface (abstract classes) design?

本文关键字:最佳 方法 抽象类 接口      更新时间:2023-10-16

我已经搜索过这个话题,但没有找到相关的答案…

假设我有一个这样声明的抽象类:

class Abstract{
    virtual Interface* createHandle() = 0;
    virtual ~Abstract() = 0;
};

基本上,一个抽象类,它提供一个唯一的函数,返回类Interface(也是一个抽象类)的任何实现。

我想知道这样的设计如何处理错误。如果createHandle()遇到一个错误,不能返回一个指针接口的实现,什么是最好的方法来处理和通知正确?

我想到的第一件事是返回一个空指针,然后在调用代码中检查返回的指针是否为空。它会工作,但我发现这相当糟糕的设计,因为接口(即抽象)从来没有暗示createHandle()可以返回一个空指针,或者返回一个空指针来表示错误(我发现相当糟糕的事实只是留下一个评论说"应该返回null如果错误")。

然后,我想到在接口指针中携带这些信息。也就是说,将两个公共非虚函数添加到设置/获取某种错误代码的类中。但是我一点也不喜欢它,因为它与Interface类无关,而是与Interface不知道的createHandle()的实现(即有一个成员变量存储与使用这个类的代码相关的错误,在我看来这感觉非常错误,尽管我可能是错的)。

我想知道,在发生错误的情况下,什么是一种优雅的方式来指定这个函数将如何表现(以一种完全独立于任何实现的方式,实际上完全相反:强迫实现按照指定的方式处理错误)。

如果情况异常并且必须处理,则可以抛出exception(尽管不能强制执行,但至少标记为异常情况)。否则返回nullptr完全可以。

例如,如果你想读取一个可能不存在的文件——这不是一个程序错误,这是一个预期的情况,所以返回nullptr的FileReader是有意义的。

也表明nullptr是一个有效的想法,并强制检查,您可以返回boost::Optional或您自己的可选类,也可能包含错误代码。

如果你开启了异常,那么异常就是一个选项。

您可以选择抛出异常或返回nullptr,但不能同时选择两者。

我建议抛出异常,因为它告诉调用者问题的确切原因,而null是沉默的。