代码之家  ›  专栏  ›  技术社区  ›  Head Geek

从构造函数的初始值设定项列表捕获异常

  •  46
  • Head Geek  · 技术社区  · 16 年前

    这是一个奇怪的。我有一个类A。它有一个类B的项,我想使用初始值设定项列表在a的构造函数中初始化它,如下所示:

    class A {
        public:
        A(const B& b): mB(b) { };
    
        private:
        B mB;
    };
    

    是否有一种方法可以捕获在仍使用初始值设定项列表方法时可能由MB的复制构造函数引发的异常?或者我必须在构造函数的大括号内初始化MB才能进行try/catch?

    5 回复  |  直到 7 年前
        1
  •  80
  •   Adam Wright    7 年前

    读一读 http://weseetips.wordpress.com/tag/exception-from-constructor-initializer-list/ )

    编辑:经过更多的挖掘,这些被称为“功能试块”。

    我承认我也不知道,直到我去寻找。你每天都在学习!我不知道这是否是我最近很少使用C++的罪名,我缺乏C++知识,或者是经常浪费语言的拜占庭特征。啊,好吧-我还是喜欢它:)

    为了确保人们不必跳到另一个站点,构造函数的函数try块的语法是:

    C::C()
    try : init1(), ..., initn()
    {
      // Constructor
    }
    catch(...)
    {
      // Handle exception
    }
    
        2
  •  16
  •   Michael Burr    16 年前

    不是特别漂亮:

    A::A(const B& b) try : mB(b) 
    { 
        // constructor stuff
    }
    catch (/* exception type */) 
    {
        // handle the exception
    }
    
        3
  •  4
  •   Mikhail Semenov    14 年前

    我知道讨论开始已经有一段时间了。但是亚当提到的Test-catch构造是C++标准的一部分,并由微软VC++和GNU C++支持。 这是有效的程序。通过这种方式,catch会自动生成另一个异常,以发出有关构造函数失败的信号。

    #include <iostream>
    #include <exception>
    #include <string>
    
    using namespace std;
    
    class my_exception: public exception
    {
      string message;
    public:
      my_exception(const char* message1)
      {
        message = message1;
      }
    
      virtual const char* what() const throw()
      {
         cout << message << endl;
         return message.c_str();
      }
    
      virtual ~my_exception() throw() {};
    };
    
    class E
    {
    public:
        E(const char* message) { throw my_exception(message);}
    };
    
    class A
    {
        E p;
    public:
        A()
      try :p("E failure")
        {
                cout << "A constructor" << endl;
        }
      catch (const exception& ex)
        {
            cout << "Inside A. Constructor failure: " << ex.what() << endl;
        }
    };
    
    
    int main()
    {
        try
        {
            A z;
        }
        catch (const exception& ex)
        {
            cout << "In main. Constructor failure: " << ex.what() << endl;
        }
        return 0;
    }
    
        4
  •  1
  •   IceFire    9 年前

    不过,您可以使用惰性初始化,也就是在MyClass中为读卡器保存一个唯一的指针,然后用new创建它。这样,您甚至不需要标记有读卡器,但您可以查看您的唯一指针是否是初始的。

    #include <iostream>
    #include <memory>
    using namespace std;
    
    class MyOtherClass
    {
    public:
        MyOtherClass()
        {
            throw std::runtime_error("not working");
        }
    };
    
    class MyClass
    {
    public:
        typedef std::unique_ptr<MyOtherClass> MyOtherClassPtr;
    
        MyClass()
        {
            try
            {
                other = std::make_unique<MyOtherClass>();
            }
            catch(...)
            {
                cout << "initialization failed." << endl;
            }
    
            cout << "other is initialized: " << (other ? "yes" : "no");
        }
    
    private:
        std::unique_ptr<MyOtherClass> other;
    };
    
    int main()
    {
        MyClass c;
    
        return 0;
    }
    

    当然,也有一些完全不使用异常的解决方案,但我认为这是您设置的前提条件。

        5
  •  0
  •   Mark Bessey    16 年前

    我不知道如何使用初始值设定项列表语法来实现这一点,但我也有点怀疑通过捕获构造函数中的异常,您是否能够做任何有用的事情。显然,这取决于类的设计,但是在什么情况下,您将无法创建“mb”,并且仍然有一个有用的“a”对象?

    您也可以让异常渗透出来,并在调用的构造函数所在的位置处理它。

    推荐文章