为了账号安全,请及时绑定邮箱和手机立即绑定

构造函数抛出异常

构造函数抛出异常

C++
一只斗牛犬 2019-12-07 15:27:48
我正在与一位同事讨论如何从构造函数中抛出异常,并认为我需要一些反馈。从设计的角度来看,可以从构造函数中抛出异常吗?可以说我将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?这样,我不必为如此低级的对象使用异常。
查看完整描述

3 回答

?
慕仙森

TA贡献1827条经验 获得超7个赞

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


查看完整回答
反对 回复 2019-12-07
?
蛊毒传说

TA贡献1895条经验 获得超3个赞

如果确实从构造函数引发异常,请记住,如果需要在构造函数初始化器列表中捕获该异常,则需要使用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

    { ... }


查看完整回答
反对 回复 2019-12-07
?
慕姐4208626

TA贡献1852条经验 获得超7个赞

#include <iostream>


class bar

{

public:

  bar()

  {

    std::cout << "bar() called" << std::endl;

  }


  ~bar()

  {

    std::cout << "~bar() called" << std::endl;


  }

};

class foo

{

public:

  foo()

    : b(new bar())

  {

    std::cout << "foo() called" << std::endl;

    throw "throw something";

  }


  ~foo()

  {

    delete b;

    std::cout << "~foo() called" << std::endl;

  }


private:

  bar *b;

};



int main(void)

{

  try {

    std::cout << "heap: new foo" << std::endl;

    foo *f = new foo();

  } catch (const char *e) {

    std::cout << "heap exception: " << e << std::endl;

  }


  try {

    std::cout << "stack: foo" << std::endl;

    foo f;

  } catch (const char *e) {

    std::cout << "stack exception: " << e << std::endl;

  }


  return 0;

}

输出:


heap: new foo

bar() called

foo() called

heap exception: throw something

stack: foo

bar() called

foo() called

stack exception: throw something

不会调用析构函数,因此,如果需要在构造函数中引发异常,则需要做很多事情(例如,清理吗?)。


查看完整回答
反对 回复 2019-12-07
  • 3 回答
  • 0 关注
  • 467 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信