【问题标题】:Finding which member in an initializer list threw an exception查找初始化列表中的哪个成员引发了异常
【发布时间】:2014-03-08 15:24:56
【问题描述】:

假设我有一个类包含某种类型的一些成员。我知道带有初始化列表的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 块。 如何判断是哪个成员初始化引发了异常?

【问题讨论】:

    标签: c++ exception constructor


    【解决方案1】:

    可以跟踪初始化过程

    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 的完美匹配

    我为 Member 提供了一个非默认构造函数来展示 构造跟踪器习语

    示例
    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++ 编译

    【讨论】:

    • 这个标准的c++怎么样?成员构造函数接受一个参数,并且提供了两个参数(我可以在链接和 c++ idioms 页面中看到它编译,但对我来说看起来很奇怪)
    • @PeterP 只传递了一个参数。带有, 的表达式计算为最后一个子表达式(数字1),因此我们用括号括起来。 (如果我必须选择一个“奇怪”的部分,那就是 TrackerType tracker 的声明/初始化)。
    【解决方案2】:
    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;
            // ...
        }
    };
    

    【讨论】:

      猜你喜欢
      • 2015-04-27
      • 1970-01-01
      • 2011-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-25
      • 2015-02-07
      • 2019-09-10
      相关资源
      最近更新 更多