c – 构造函数初始化列表中的约束检查

前端之家收集整理的这篇文章主要介绍了c – 构造函数初始化列表中的约束检查前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
这种情况与 How to make a constraint on the parameters of the constructor有关,但略有不同.

您希望初始化非默认可构造成员,但需要在构造之前检查约束.

例:

(请注意,这只是一个例子.在这种特定情况下是否应该使用无符号整数是可以讨论的,但问题实际上是关于你想检查构造函数的一般情况)

你有以下课程:

class Buffer {
public:
    Buffer() = delete;
    Buffer(int size) noexcept;
};
....


class RenderTarget {
public:
    ....
private:
    int width_,height_;
    Buffer surface_;
};

构造函数必须检查整数参数的有效性:

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");
}

注意Buffer没有默认构造函数,真正的构造函数是noexcept,即没有办法捕获错误.

当整数参数为负数时,已经有一个hosed surface_.在使用约束值之前进行约束检查会更好.可能吗?

解决方法

命名构造函数

您可以使用所谓的命名构造函数(另请参阅http://www.parashift.com/c++-faq/named-ctor-idiom.html),并将构造函数设为私有:

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);
    }

如果您有多个可能不明确使用的构造函数,则命名构造函数很有用,例如:温度< - 摄氏度|华氏温度|开尔文或距离< - 米|院子里| Cubit |公里|.公里.... 否则,(个人意见)他们强加了意想不到的抽象,也分散了注意力,应该避免. 三元运算符和抛出 C允许在[expr.cond]中将一个或两个操作数中的throw-expression用于三元运算符(?: – 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)
{}

如果你不存储参数,你也可以在表达式中使用?:当然:

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)
    )
{}

或者您将前置条件检查合并到一个操作数中:

RenderTarget(int w,int h) :
    surface_(
       (w<0||h<0) ? throw std::logic_error("Crizzle id boom shackalack") :
       w * h
    )
{}

使用带有throw-expression内联的?: – 运算符对于基本约束检查非常好,并且避免必须回退到使用默认构造函数(如果有的话),然后在构造函数体内进行“实际初始化”.

对于更复杂的场景,这可能会变得有点笨拙.

静态私人会员

当然,可以使用两全其美的优点:

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")
        )
    {}

…或者您需要为预处理检查所需的任何成员编写静态函数

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))
    {}

这很好,因为您手头有完整的C -machinery进行约束检查,例如可以轻松添加日志记录.它可以很好地扩展,但对于简单的场景来说不那么方便.

原文链接:https://www.f2er.com/c/110938.html

猜你在找的C&C++相关文章