如何在类初始化列表之前放置断言?

时间:2017-11-18 16:23:30

标签: c++ constructor initialization assert design-by-contract

在调用初始化列表之前,是否可以在类构造函数上断言某些参数?

class Foo
{
    int m_lower;
    int m_upper;
    unsigned int m_delta;

  public:
    Foo(int t_lower, int t_upper) :
        assert(t_lower < t_upper),  // Assert here, before initialisation of fields.
        m_lower(t_lower),
        m_upper(t_upper),
        m_delta(t_upper - t_lower)
    {
       // Assert could be made here, but m_delta would have underflowed if t_upper < t_lower.  
    }
}

在初始化列表之前断言的好处是可以立即对每个字段的初始化要求进行,并且不必在具有相同要求的每个初始化时多次检查。虽然m_delta的初始化可以在init_delta初始化方法中进行,但如果几个值具有与t_upper > t_lower相同的要求,则断言必须放在每个值中(如果删除了先前的断言)。如果放置构造函数本身,那么一个或多个字段的初始化可能已经失败(有一些比下溢更具戏剧性的东西)。

如果放在初始化列表的顶部,那么合同在检查时对用户都是清楚的,并且会在出现任何错误之前标记错误,例如在这种情况下会发生下溢。

上述案例只是该问题的简化示例。我知道有更好的方法来解决上面的具体问题(abs()等)。

感谢您的帮助和建议!

1 个答案:

答案 0 :(得分:3)

您可以使用逗号运算符:

  public:
    Foo(int t_lower, int t_upper) :
        m_lower(assert(t_lower < t_upper), t_lower),
        m_upper(t_upper),
        m_delta(t_upper - t_lower)
    {
        ...
    }

逗号运算符的操作数从左到右进行计算,右侧值用作结果。

请注意,初始化的顺序基于成员变量在类中声明的顺序,而不是初始化列表中的顺序。所以你应该把assert()调用放在第一个成员变量的初始化中。