首页 > 解决方案 > 没有 try/catch 块的构造函数的 C++ 异常处理

问题描述

在我目前正在进行的一个学校项目中,我们必须写入和读取二进制文件。为了使我的代码更优雅,我选择在其中一个类中使用序列化 ctor,这些类接收一个 ifstream 以从文件中读取以获取其适当的数据。

我们的要求之一是我们需要检查文件是否成功读取,但还不允许以 try-catch 块的形式实现异常处理。所以我能想到的唯一选择是如果读取不成功则返回一个布尔值。问题是我有嵌套类,例如第一个类看起来像:

class A
{
public:
    A(ifstream& input)
    {
      // read data from input //
      // call load method of nested class B  // 
     }

private:
   // some data // 
   B b;
};

并且嵌套类将调用其 load 方法来读取适当的数据,而不是具有接收文件的 ctor,因此 B 将如下所示:

class B
{
public:
   void load(ifstream& input);

private:
    // some data // 
};

处理异常的替代方法是什么,或者您建议对我的代码进行哪些更改以使其符合项目要求?

将 B 的加载方法设为布尔值,并返回 false,例如,如果读数不好,会导致我回到 A 的 ctor,我无法从中返回值。

我现在用 C++ 编码了几个月,所以如果这里的某些东西看起来像是糟糕的设计或明显的错误,我深表歉意 - 也将不胜感激任何反馈。谢谢你。

标签: c++exceptionconstructortry-catch

解决方案


如果你不能从构造函数中抛出,你可能需要一个静态工厂,它也允许返回“错误”

有一些建议std::expected<T, Error>,但还没有,一些图书馆可能会提出等效的建议。

目前可能的方法包括使用std::optional或(智能)指针:

class B
{
    B() = default;
public:
    static std::optional<B> load(std::istream& input)
    {
        B b;
        // read input...
        if (errorDetected) { return std::nullopt; }
        return b;
    }

private:
    // some data
};
class A
{
public:
    static load(std::istream& input)
    {
        A a;
        // read data from input
        if (errorDetected) { return std::nullopt; }

        auto b = B::load(input);
        if (!b) return std::nullopt;
        a.b = std::move(*b);

        return a;
    }

private:
   // some data
   B b;
};

没有std,optional可能会很快实现(有几个警告,但它可能已经足够好了),例如:

template <typename T>
class my_poor_optional
{
    T data; // required to be constructed, even when invalid contrary to real optional
    bool is_valid = false;
public:
    // ...
};

推荐阅读