我一般不会使用无效对象方法,因为我认为这是一个糟糕的设计.构造之后,对象必须处于建立不变量的状态(这是构造函数应该服务的唯一目的).考虑一个strange_vector实现类似的类std::vector,但在调用之后strange_vector<int>(10, 0),该对象将处于不可用状态,因为分配失败.
相反,我会将构造函数声明为private并使用返回可选的工厂方法:
class file
{
public:
~file() {fclose(m_file);}
static std::optional<file> open(std::string const& filename)
{
auto f = fopen(filename.c_str(), "r");
if (f)
{
return std::make_optional<file>(f);
}
else
{
return std::nullopt;
}
}
private:
file(FILE* file);
FILE* m_file;
};
Run Code Online (Sandbox Code Playgroud)
异常处理的最大好处之一是(除了解耦错误处理和正常的代码路径),你不能意外地忽略它们.如果你想要,你可以创建自己的类optional,当没有用有效对象初始化时,记录错误消息并终止你的程序(或任何其他合理的错误处理).我认为A. Alexandrescu有一个关于系统错误处理的讨论,他实现了一个Expected<T>包含类型值T或异常的类.您可以使用此基础而不是异常添加您的错误处理.
std::optional 它不是标准的一部分,但您可以轻松地将实现作为最近编译器,boost或其他库的一部分.