构造函数生成

Constructor generation

本文关键字:构造函数      更新时间:2023-10-16

我有两个C++结构,Rect是一个浮点矩形,iRect是相同的,但有整数:

struct iRect {
    int X;
    int Y;
    int W;
    int H;
};
struct Rect {
    float X;
    float Y;
    float W;
    float H;
};

目前,我可以使用语法Rect{1.2, 2.4, 4.2, 0.2};来构造这些。

现在我想让这些隐式转换,所以我为Rect:创建了一个新的构造函数

Rect(iRect iR) {
    X = (float)iR.X;
    Y = (float)iR.Y;
    W = (float)iR.W;
    H = (float)iR.H;
}

我得到:error C2512: 'Rect' : no appropriate default constructor available没什么大不了的,我只定义一个空的默认构造函数。

但现在我得到了error C2440: 'initializing' : cannot convert from 'initializer-list' to 'Rect'

因此,我必须为四个浮点、三个浮点、两个浮点和一个浮点定义另一个构造函数,以便具有与以前相同的行为。这个例子也被简化了:Rect实际上也是两个Vec2类型的并集,所以我还必须为Rect (Vec2 a, Vec2 b)定义一个构造函数。

通常,所有这些构造函数都是由编译器生成的。有没有什么方法可以在不阻止编译器生成所有其他构造函数的情况下定义我的Rect(iRect iR)构造函数?

与其定义构造函数,不如定义转换运算符:

struct iRect {
    ...
    operator Rect() const {
        return Rect{X,Y,W,H};
    }
};

每当iRect必须隐式或显式转换为Rect时,转换运算符就会生效(可以添加explicit关键字以将其限制为仅显式转换(。定义了这个运算符后,您现在可以编写

iRect a;
Rect b = a;

正如你所料。

由于转换运算符不是构造函数,所以它们不会抑制默认构造函数——所有聚合初始化都将继续工作。

使用转换函数。这种类型的设计在许多库中实现(脑海中浮现的是Qt(。此外,您的转换构造函数在没有任何原因的情况下接受iRect副本,并且您应该在可能的情况下使用C++样式的强制转换。你可以简单地写:

Rect toRect(const iRect& i)
{
    Rect r;
    r.X = static_cast<float>(i.X);
    r.Y = static_cast<float>(i.Y);
    r.W = static_cast<float>(i.W);
    r.H = static_cast<float>(i.H);
    return r;
}

编辑:该死,@dyp打败了我。

问题是,如果没有构造函数,就会存在默认的聚合初始值设定项,请参阅此处。当定义一个自定义构造函数(我可能会说任何一个(时,聚合初始化就不再可能了。

正如其他人指出的那样,最好定义一个转换运算符

struct iRect {
    //...
    /* explicit */ operator Rect() const {
        return Rect{X,Y,W,H};
    }
};

可以添加explicit,以便必须显式进行铸造,例如:

iRect r {1, 2, 3, 4};
Rect r2 = (Rect) r; // Explicit cast