带有多个参数的显式构造函数


88

使构造函数具有多个参数explicit是否有任何(有用的)效果?

例:

class A {
    public:
        explicit A( int b, int c ); // does explicit have any (useful) effect?
};

Answers:


120

直到C ++ 11,是的,没有理由explicit在multi-arg构造函数上使用。

由于初始化列表,C ++ 11中的情况发生了变化。基本上,使用初始化程序列表进行复制初始化(而不是直接初始化)需要不标记构造函数explicit

例:

struct Foo { Foo(int, int); };
struct Bar { explicit Bar(int, int); };

Foo f1(1, 1); // ok
Foo f2 {1, 1}; // ok
Foo f3 = {1, 1}; // ok

Bar b1(1, 1); // ok
Bar b2 {1, 1}; // ok
Bar b3 = {1, 1}; // NOT OKAY

5
我认为使用“我为什么想要”或“何时有用”的解释会更好。
MateuszL,

@MateuszL Edgar的答案可能是最好的论据,说明了为什么它可能有用(并且值得一提)。不过,之所以存在,仅仅是因为它是的现有语义的逻辑扩展explicit。我个人不会打扰到multi-arg构造函数explicit
Sneftel

31

您会偶然发现它以进行大括号初始化(例如在数组中)

struct A {
        explicit A( int b, int c ) {}
};

struct B {
         B( int b, int c ) {}
};

int main() {
    B b[] = {{1,2}, {3,5}}; // OK

    A a1[] = {A{1,2}, A{3,4}}; // OK

    A a2[] = {{1,2}, {3,4}}; // Error

    return 0;
}

24

主要原因是@StoryTeller和@Sneftel给出的出色答案。但是,恕我直言,这是有道理的(至少我是这样做的),作为以后校对代码的将来更改的一部分。考虑您的示例:

class A {
    public:
        explicit A( int b, int c ); 
};

此代码不会直接从中受益explicit

一段时间后,您决定为添加一个默认值c,因此它变为:

class A {
    public:
        A( int b, int c=0 ); 
};

这样做时,您将重点放在c参数上-回想起来,它应该具有默认值。您不必专注于是否A应隐式构造自身。不幸的是,这种改变explicit再次变得有意义。

因此,为了传达一个ctor是explicit,在首次编写该方法时可能需要这样做。


但是,当维护者添加该默认值并得出结果可作为转换构造函数使用的情况时,情况又如何呢?现在,他们不得不删除explicit是一直在那里,直到永远,技术支持将与有关变革的要求所淹没,并花时间解释,explicit只是噪音,并删除它是无害的。就我个人而言,我不太擅长预测未来。很难确定接口现在应该是什么样子。
皮特·贝克尔,2016年

@PeteBecker很好。我个人认为这两种情况是不对称的,并且在将参数设为默认值(或将其删除)时无意中使类隐式可构造,然后实际上意识到回想起来应该更是如此。话虽如此,这些是“软”的考虑因素,可能在人/项目/等之间有所不同,甚至只是一个品味问题。
阿米·塔沃里

8

这是我的五分钱:

struct Foo {
    Foo(int, double) {}
};

struct Bar {
    explicit Bar(int, double) {}
};

void foo(const Foo&) {}
void bar(const Bar&) {}

int main(int argc, char * argv[]) {
    foo({ 42, 42.42 }); // valid
    bar({ 42, 42.42 }); // invalid
    return 0;
}

如您所见,explicit阻止将初始化程序列表与bar函数一起使用,因为的构造函数struct Bar声明为explicit

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.