查找初始化列表中的哪个成员引发异常

时间:2014-03-07 21:00:39

标签: c++ exception constructor

假设我有一个班级,其中包含某些类型的成员。我知道带有初始化列表的try-catch块的语法如下

template<int N>
struct Member
{
    Member()
    {
        std::cout << "Default constructor of Member " << N << std::endl;
    }
};

class A 
{
    Member<1> m1;
    Member<2> m2;
    // n members 
public:
A() try
    : m1()
    , m2()
    {
        // constructor implementation
    }
    catch (std::exception const & e)
    {
               // ... cleanup 
        throw; // and rethrow
    }
};

由于涉及初始化列表,我不能使用多个try catch块。 如何判断哪个成员初始化引发了异常?

2 个答案:

答案 0 :(得分:3)

您可以跟踪初始化过程

class A 
{
    Member<1> m1;
    bool m1threw = true;
    Member<2> m2;
    bool m2threw = true;
    // n members 
public:
A() try
    : m1()
    , m1threw(false)
    , m2()
    , m2threw(false)
    {
        // constructor implementation
    }
    catch (std::exception const & e)
    {
               // ... cleanup 
        if (m1threw) {
            // 
        }
        else if (m2threw) {

        }
        throw; // and rethrow
    }
};

注意在类初始化中仅在c ++ 11中有效。使您的示例更复杂的原因是成员变量是默认构造的。如果他们的构造函数接受了一个参数,那么这将是construction tracker idiom

的完美匹配

我向会员提供了一个非默认构造函数来展示构建跟踪器习惯用法的示例

template<int N>
struct Member
{
    Member(int some_arg) 
    {
        std::cout << "Non default constructor of Meber " << N << std::endl;
    }
};

class A 
{
    Member<1> m1;
    Member<2> m2;
   enum TrackerType { NONE, ONE, TWO };
public:
   A(TrackerType tracker = NONE)
   try    // A constructor try block.
     : m1((tracker = ONE, 1)) // Can throw std::exception
     , m2((tracker = TWO, 1)) // Can throw std::exception
     {
         //TODO:
     }
   catch (std::exception const & e)
     {
        if (tracker == ONE) {
           std::cout << "m1 threw: " << e.what() << std::endl;
        }
        else if (tracker == TWO) {
           std::cout << "m2 threw: " << e.what() << std::endl;
        }
        throw;
     }
};

基本上这不需要额外的成员来实现跟踪as you can see并且可以在11之前用c ++编译

答案 1 :(得分:1)

template<int N>
struct Member
{
    Member()
    {
        std::cout << "Default constructor of Member " << N << std::endl;
        // ...
        if (bad_thing)
        {
            throw N;
        }
    }
};

class A 
{
    Member<1> m1;
    Member<2> m2;
    // n members 
public:
A() try
    : m1()
    , m2()
    {
        // ...
    }
    catch (int N)
    {
        std::cout << "construction of member " << N << " failed" << std::endl;
        // ...
    }
};