Seb*_*ach 9 c++ initialization constraints initialization-list
这种情况与如何对构造函数的参数进行约束有关,但它略有不同.
您想要初始化非默认可构造成员,但需要在构造之前检查约束.
(请注意,这只是一个例子.在这种特定情况下是否应该使用无符号整数是可以讨论的,但问题实际上是关于你想检查构造函数的一般情况)
你有以下课程:
class Buffer {
public:
Buffer() = delete;
Buffer(int size) noexcept;
};
....
class RenderTarget {
public:
....
private:
int width_, height_;
Buffer surface_;
};
Run Code Online (Sandbox Code Playgroud)
构造函数必须检查整数参数的有效性:
RenderTarget::RenderTarget(int width, int height) :
width_(width), height_(height),
surface_(width_*height)
{
if (width_<0 || height_<0)
throw std::logic_error("Crizzle id boom shackalack");
}
Run Code Online (Sandbox Code Playgroud)
注意如何Buffer没有默认构造函数,而真正的构造函数是noexcept,即没有办法捕获错误.
当整数参数为负数时,已经有一个surface_已经加了.在使用约束值之前进行约束检查会更好.可能吗?
Seb*_*ach 17
您可以使用所谓的命名构造函数(另请参阅http://www.parashift.com/c++-faq/named-ctor-idiom.html),并创建构造函数private:
class RenderTarget {
private:
RenderTarget (int w, int h) :
width_(w), height_(h), buffer_(w*h)
{
// NOTE: Error checking completely removed.
}
public:
static RenderTarget create(int width, int height) {
// Constraint Checking
if (width<0 || height<0)
throw std::logic_error("Crizzle id boom shackalack");
return RenderTarget(width, height);
}
Run Code Online (Sandbox Code Playgroud)
如果您有多个可能不明确使用的构造函数,则命名构造函数很有用,例如Temperature < - Celsius | 华氏温度| 开尔文或距离< - 米| 院子里| Cubit | 公里|.公里 ....
否则,(个人意见)他们强加意想不到的抽象和分心,应该避免.
throwC++允许在[expr.cond]中使用-expressionsthrow作为三元运算符(-operator)的一个或两个操作数?::
RenderTarget(int w, int h) :
width_(w<0 ? throw std::logic_error("Crizzle id boom shackalack") : w),
height_(h<0 ? throw std::logic_error("Crizzle id boom shackalack") : h),
surface_(w*h)
{}
Run Code Online (Sandbox Code Playgroud)
如果你不存储参数,你?:当然也可以在表达式中使用:
RenderTarget(int w, int h) :
surface_(
(w<0 ? throw std::logic_error("Crizzle id boom shackalack") : w)
* (h<0 ? throw std::logic_error("Crizzle id boom shackalack") : h)
)
{}
Run Code Online (Sandbox Code Playgroud)
或者将前置条件检查合并到一个操作数中:
RenderTarget(int w, int h) :
surface_(
(w<0||h<0) ? throw std::logic_error("Crizzle id boom shackalack") :
w * h
)
{}
Run Code Online (Sandbox Code Playgroud)
使用?:带有throw-expression 内联的-operator 对于基本约束检查非常好,并且避免必须回退到使用默认构造函数(如果有的话),然后在构造函数体内进行"实际初始化".
对于更复杂的场景,这可能会变得有点笨拙.
当然,可以使用两全其美的优点:
private:
static bool check_preconditions(int width, int height) {
if (width<0 || height<0)
return false;
return true;
}
public:
RenderTarget(int w, int h) :
surface_(
check_preconditions(w,h) ?
w*h :
throw std::logic_error("Crizzle id boom shackalack")
)
{}
Run Code Online (Sandbox Code Playgroud)
...或者您需要为预处理检查所需的任何成员编写静态函数:
private:
static Buffer create_surface(int width, int height) {
if (width<0 || height<0)
throw std::logic_error("Crizzle id boom shackalack")
return Buffer(width*height);
}
public:
RenderTarget(int w, int h) :
surface_(create_surface(w, h))
{}
Run Code Online (Sandbox Code Playgroud)
这很好,因为您拥有完整的C++ - 用于约束检查的机器,例如可以轻松添加日志记录.它可以很好地扩展,但对于简单的场景来说不那么方便.