有人张贴explicit关键字在 c + + 的含义的另一个问题的说明。因此,它意味着什么?

2008-09-23 13:58:45
问题评论:

我只想指出新随后沿,自从 C + + 11,explicit可应用于多个构造函数的任何人。现应用于转换运算符以及时有效。假设您有一个类BigIntint转换运算符和std::string为显式转换运算符无论出于什么原因。您可以说int i = myBigInt;,但您必须显式强制转换 (使用static_cast,最好) 要说std::string s = myBigInt;.

不能显式也指分配?(如int x(5);)

theunixshell.blogspot.com/2013/01/explicit-keyword-in-c.html

回答:

在 c + +,编译器允许进行一个解析为一个函数的参数的隐式转换。这意味着,编译器可以使用可调用的构造函数具有单个参数从一种类型转换为另一以获得正确的类型参数。下面是示例类具有构造函数可用于隐式转换︰

class Foo
{
public:
  // single parameter constructor, can be used as an implicit conversion
  Foo (int foo) : m_foo (foo) 
  {
  }

  int GetFoo () { return m_foo; }

private:
  int m_foo;
};

下面是一个简单的函数,采用一个Foo对象︰

void DoBar (Foo foo)
{
  int i = foo.GetFoo ();
}

并且这里是在调用DoBar函数。

int main ()
{
  DoBar (42);
}

该参数不是一个Foo对象,而int但是,采用一个int ,因此可以使用此构造函数将参数转换为正确的类型中的Foo存在构造函数。

编译器可以执行一次此为每个参数。

在构造函数的explicit关键字前面可以防止编译器使用该构造函数进行隐式转换。将其添加到上面的类将创建在函数调用DoBar (42)编译器错误。现在有必要寻求DoBar (Foo (42))使用显式转换

您可能要这样做的原因是为了避免意外的构造,可以隐藏 bug。刻意的示例︰

  • 有一个MyString(int size)类具有构造函数用于构造给定大小的字符串。print(const MyString&)函数,并与print(3)调用它。您希望打印"3",但打印空字符串的长度为 3。

很好写的了,您可能想要说与默认参数的多参数构造还充当一个 arg ctor 如对象 (const char * 名称 = NULL,int otype = 0)。

我认为它应该还包括一个应考虑使单个参数的构造函数最初明确 (或多或少),自动删除 explicit 关键字的隐式转换时才想要通过设计和。我认为 contructors 应显式默认情况下,具有隐式的关键字,以使他们能够作为隐式转换工作。但这并没有对其进行方式。

@thecoshman︰ 不要声明参数explicit构造函数explicit声明。但是: Foo类型参数必须是构造的explicitely,他们不会以静默方式构造的只将其构造函数的参数插入到该函数。

只是 FYI 当调用"print(3)"在您的示例中,该函数需要能够"打印 (const MyString &")。"Const"是必填字段这里因为 3 转换为临时的"MyString"对象,并不能将一个临时绑定到引用,除非它尚"const"(另一个在 c + + 陷阱的长列表)

为完整起见,我添加的参数转换除了explicit关键字还将防止使用分配表单的副本 ctor (如 Foo myFoo = 42;),并且需要显式形式 Foo myFoo = Foo(42); 或 Foo myFoo(42);

假设您有一个类字符串︰

class String {
public:
    String(int n); // allocate n bytes to the String object
    String(const char *p); // initializes object with char *p
};

现在,如果您尝试

String mystring = 'x';

字符 x 将隐式转换为 int,然后将调用 String(int) 构造函数。但这并不是用户可能有想。因此,为了防止这种情况,我们应将该构造函数定义为explicit:

class String {
public:
    explicit String (int n); //allocate n bytes
    String(const char *p); // initialize sobject with string p
};

I + 1 教育这因为它有没有void main,它解释了为什么一个使用它,而不是只是 explaning 的含义。

值得注意的新通用的 C + + 0 x 将初始化规则和String s = {0};格式错误,而不尝试调用其他构造函数,用 null 指针,String s = 0;则不然。

即使这是一个旧的问题似乎值得指出的几种方法 (或让某个人设置我直)。使 int 窗体或这两种构造,通过显式仍必须相同的错误如果您使用String mystring('x') ,当您是String mystring("x")吗?同时,从上面的评论我认为改进的行为的String s = {0}String s = 0由于使 ctor int 窗体显式。但不知道构造的优先级如何知道目的 (即如何发现 bug) 此String s{0} ?

@InQusitive: 'x'被视为一个整数,因为char数据类型是只是一个 1 字节整数.

您的示例的问题是,它只有在复制初始化(使用=) 但不是与直接初始化(不使用=)︰ 编译器将不会生成错误如果您编写的String mystring('x');,正如 @Arbalest 指出仍调用String(int)构造函数。explicit关键字用于防止直接初始化解析函数中发生的隐式转换。更好的解决方案为您的示例是一个简单的构造函数重载︰String(char c);.

C + + 中只能有一个所需参数的构造函数被视为隐式转换函数。它将参数类型转换为类类型。这是一件好事还是不取决于构造函数的语义。

例如,如果您有一个字符串类具有构造函数String(const char* s),这正是可能您的希望。您可以传递const char*给需要String,函数,编译器将为您自动构造一个临时String对象。

另一方面,如果您有您可能不希望编译器Buffer(int size)将缓冲区的大小,以字节为单位,其构造函数的缓冲区类安静地变为intsBuffers。若要避免此问题,您可以声明构造函数用explicit关键字︰

class Buffer { explicit Buffer(int size); ... }

这样一来,

void useBuffer(Buffer& buf);
useBuffer(4);

将成为编译时错误。如果您想要通过一个临时Buffer对象,您必须显式执行此操作︰

useBuffer(Buffer(4));

总之,如果您单参数的构造函数将参数转换为您的类的对象您可能不希望使用explicit关键字。但是,如果有只是碰巧带单个参数的构造函数时,应将其声明为explicit以防止编译器您惊人的意外转换。

explicit关键字使非转换构造函数转换构造函数。因此,代码是较少出错。

此答案在于有无显式构造函数创建对象,因为它不涉及其他答案。

请考虑下面的类,而无需显式构造函数︰

class Foo
{
public:
    Foo(int x) : m_x(x)
    {
    }

private:
    int m_x;
};

可以两种方式创建 Foo 类对象︰

Foo bar1(10);

Foo bar2 = 20;

具体实现,第二个实例化类 Foo 的方式可能会带来麻烦,或者没有什么程序员想。作为前缀给构造函数的explicit关键字将生成编译器错误在Foo bar2 = 20;.

它是通常好的做法将单个参数的构造函数声明为explicit,除非您实现明令禁止。

还要注意,构造函数的

  • 默认参数对于所有参数,或
  • 此后的第二个参数的默认参数

既可作为单一参数的构造函数。因此,要使这些也explicit.

举例来说,当您将故意想明确您单参数的构造函数是如果您正在创建仿函数 (在答案中声明该 add_x 结构查看)。在这种情况下,创建一个作为对象add_x add30 = 30;可能会很有用。

这里是良好的撰写上显式的构造函数。

内容来源于Stack Overflow What does the explicit keyword in C++ mean?
请输入您的翻译

What does the explicit keyword in C++ mean?

确认取消