何时在 C++ 中显式构造函数 [关闭]

问题描述 投票:0回答:1

阅读以下博客后:

http://xania.org/200711/ambiguously-overloading

我开始问自己“我不应该总是显式定义我的构造函数吗?”

所以我开始阅读更多的内容,而不是发现这篇文章:

http://www.sjbrown.co.uk/2004/05/01/always-use-explicit/

这展示了另一个例子,也解释了他背后的想法。 但这当然是一位博主的想法。

我很高兴听到你们中的一些人的意见,你们对这种方式的看法,你们对这个主题的经验是什么,以及任何一种方式的一些例子都会很好。

c++ constructor explicit defensive-programming explicit-constructor
1个回答
69
投票

传统的观点是,构造函数采用一个参数(通过使用默认参数显式地或有效地)应该标记为

explicit
,除非它们确实定义了一个转换(
std::string
可以从
const char*
转换为一个示例)后者)。您自己已经找出了原因,因为隐式转换确实会让生活变得比原来更困难。

一个明显的例外可能是复制构造函数。或者也许另一种方法是考虑大多数类型可以相互转换,因此复制构造函数在大多数情况下都没有标记为

explicit

虽然看起来标记所有其他类型的构造函数

explicit
并没有什么坏处,但我反对它。因为虽然
explicit
对 C++03 中采用多个参数的构造函数没有影响,但它在 C++11 中确实有影响。将其放入代码中:

struct foo {
    explicit foo(int i);
    foo(int i, int j);
    explicit foo(int i, int j, int k);
};

foo make_foo()
{
    /* Not C++11-specific: */
    // Error: no conversion from int to foo
    return 42;

    // Okay: construction, not conversion
    return foo(42);

    // Okay: constructions
    return foo(42, 42);
    return foo(42, 42, 42);

    /* C++11 specific: */
    // Error: no conversion from int to foo
    return { 42 };

    // Not an error, not a conversion
    return { 42, 42 };

    // Error! Constructor is explicit
    return { 42, 42, 42 };
    // Not an error, direct-initialization syntax
    return foo { 42, 42, 42 };
}

我个人认为,在返回

foo
的函数中,我必须显式返回
foo { 42, 42, 42 }
,这是不必要的冗长。我不明白
explicit
正在保护我免受什么侵害。我真的希望
{ initializers... }
语法意味着“从给定的初始化器构造对象”,而
explicit
进入了这种方式,同时又让我免于一无所获。 (因为在复制初始化的上下文中,
{ i }
确实归结为
i
——大多数时候——我很乐意放弃这个。)

所以我想说要养成对一元构造函数使用

explicit
的习惯,仅限这些

© www.soinside.com 2019 - 2024. All rights reserved.