从构造函数中抛出异常

新手上路,请多包涵

我正在与一位同事就从构造函数中抛出异常进行辩论,并认为我想要一些反馈。

从设计的角度来看,可以从构造函数中抛出异常吗?

假设我在一个类中包装了一个 POSIX 互斥体,它看起来像这样:

 class Mutex {
public:
  Mutex() {
    if (pthread_mutex_init(&mutex_, 0) != 0) {
      throw MutexInitException();
    }
  }

  ~Mutex() {
    pthread_mutex_destroy(&mutex_);
  }

  void lock() {
    if (pthread_mutex_lock(&mutex_) != 0) {
      throw MutexLockException();
    }
  }

  void unlock() {
    if (pthread_mutex_unlock(&mutex_) != 0) {
      throw MutexUnlockException();
    }
  }

private:
  pthread_mutex_t mutex_;
};

我的问题是,这是标准的做法吗?因为如果 pthread mutex_init 调用失败,互斥对象将不可用,因此抛出异常可确保不会创建互斥对象。

我是否应该为 Mutex 类创建一个成员函数 init 并调用 pthread mutex_init 在其中将返回一个基于 pthread mutex_init 的返回的布尔值?这样我就不必为这样一个低级别的对象使用异常。

原文由 lkristjansen 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 499
2 个回答

是的,从失败的构造函数中抛出异常是执行此操作的标准方法。阅读有关 处理失败的构造函数的 常见问题解答以获取更多信息。有一个 init() 方法也可以,但是每个创建 mutex 对象的人都必须记住必须调用 init()。我觉得这违反了 RAII 原则。

原文由 Naveen 发布,翻译遵循 CC BY-SA 3.0 许可协议

请注意 the destructor never gets called after the exception is thrown from the constructor

 struct B
{
    char* p;
    B() {
        cout << "Constructor - B" << endl;
        p = new char[1024];
        throw std::exception("some exception");
    }
    ~B() { // NEVER GETS CALLED AFTER EXCEPTION !!!! - memory leak
        cout << "Destructor - B" << endl;
        delete[] p;
    }
};

int main()
{
    try {
        B b;
    }
    catch (...) {
        cout << "Catch called " << endl;
    }
}

输出:

 Constructor - B
Catch called       (Note: B's Destructor is NEVER called)

原文由 SridharKritha 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题