猿问

构造函数抛出异常

我正在与一位同事讨论如何从构造函数中抛出异常,并认为我需要一些反馈。


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


可以说我将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?这样,我不必为如此低级的对象使用异常。


一只斗牛犬
浏览 484回答 3
3回答

慕仙森

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

蛊毒传说

如果确实从构造函数引发异常,请记住,如果需要在构造函数初始化器列表中捕获该异常,则需要使用try / catch语法。例如func::func() : foo(){    try {...}    catch (...) // will NOT catch exceptions thrown from foo constructor    { ... }}与func::func()    try : foo() {...}    catch (...) // will catch exceptions thrown from foo constructor    { ... }

慕姐4208626

#include <iostream>class bar{public:&nbsp; bar()&nbsp; {&nbsp; &nbsp; std::cout << "bar() called" << std::endl;&nbsp; }&nbsp; ~bar()&nbsp; {&nbsp; &nbsp; std::cout << "~bar() called" << std::endl;&nbsp; }};class foo{public:&nbsp; foo()&nbsp; &nbsp; : b(new bar())&nbsp; {&nbsp; &nbsp; std::cout << "foo() called" << std::endl;&nbsp; &nbsp; throw "throw something";&nbsp; }&nbsp; ~foo()&nbsp; {&nbsp; &nbsp; delete b;&nbsp; &nbsp; std::cout << "~foo() called" << std::endl;&nbsp; }private:&nbsp; bar *b;};int main(void){&nbsp; try {&nbsp; &nbsp; std::cout << "heap: new foo" << std::endl;&nbsp; &nbsp; foo *f = new foo();&nbsp; } catch (const char *e) {&nbsp; &nbsp; std::cout << "heap exception: " << e << std::endl;&nbsp; }&nbsp; try {&nbsp; &nbsp; std::cout << "stack: foo" << std::endl;&nbsp; &nbsp; foo f;&nbsp; } catch (const char *e) {&nbsp; &nbsp; std::cout << "stack exception: " << e << std::endl;&nbsp; }&nbsp; return 0;}输出:heap: new foobar() calledfoo() calledheap exception: throw somethingstack: foobar() calledfoo() calledstack exception: throw something不会调用析构函数,因此,如果需要在构造函数中引发异常,则需要做很多事情(例如,清理吗?)。
随时随地看视频慕课网APP
我要回答