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

Posted

技术标签:

【中文标题】带多个参数的显式构造函数【英文标题】:Explicit constructor taking multiple arguments 【发布时间】:2016-12-31 12:25:23 【问题描述】:

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

例子:

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

【问题讨论】:

【参考方案1】:

直到 C++11,是的,没有理由在多参数构造函数上使用 explicit

这在 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

【讨论】:

我认为用“我为什么要那个”或“这什么时候有用”的解释来回答会更好。 @MateuszL Edgar 的回答可能是最好的论据,说明它为什么有用(并且可以说值得打勾)。然而,它那里的原因仅仅是因为它是explicit 现有语义的逻辑扩展。我个人不会费心制作多参数构造函数explicit【参考方案2】:

你会偶然发现它用于大括号初始化(例如在数组中)

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[] = A1,2, A3,4; // OK

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

    return 0;

【讨论】:

【参考方案3】:

@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只是噪音,并且删除它是无害的。就个人而言,我不太擅长预测未来; 现在决定界面应该是什么样子已经够难的了。 @PeteBecker 说得好。我个人认为这两种情况是不对称的,并且在使参数默认(或删除它们)以无意中使类隐式构造时更为常见,然后同时实际意识到回想起来应该是这样。话虽如此,这些都是“软”考虑,可能因人/项目/等而异,甚至只是品味问题。【参考方案4】:

这是我对这次讨论的五分钱:

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

【讨论】:

以上是关于带多个参数的显式构造函数的主要内容,如果未能解决你的问题,请参考以下文章

C++17 中的显式默认构造函数

为啥我的显式构造函数会为我的转换运算符创建这种歧义?

operator== 和 boost::detail::atomic_count 中的显式构造函数?

真的没有来自 std::string_view 的 std::string 的显式构造函数吗?

运算符重载中的显式构造?

java基础