在调用初始化列表之前,是否可以断言类构造函数上的参数?
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()等)。
谢谢你的帮助和建议!
您可以使用逗号运算符:
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()
调用放在第一个成员变量的初始化中。