什么是 C++ 中的转换构造函数?它有什么用?

2021-12-30 00:00:00 constructor c++ copy-constructor

我听说 C++ 有一种叫做转换构造函数"或转换构造函数"的东西.这些是什么,它们有什么用?我看到它提到了有关此代码的内容:

I have heard that C++ has something called "conversion constructors" or "converting constructors". What are these, and what are they for? I saw it mentioned with regards to this code:

class MyClass
{
  public:
     int a, b;
     MyClass( int i ) {}
}

 int main()
{
    MyClass M = 1 ;
}

推荐答案

转换构造函数的定义在 C++03 和 C++11 之间是不同的.在这两种情况下,它都必须是非explicit 构造函数(否则它不会参与隐式转换),但对于 C++03,它也必须可以使用单个参数调用.即:

The definition for a converting constructor is different between C++03 and C++11. In both cases it must be a non-explicit constructor (otherwise it wouldn't be involved in implicit conversions), but for C++03 it must also be callable with a single argument. That is:

struct foo
{
  foo(int x);              // 1
  foo(char* s, int x = 0); // 2
  foo(float f, int x);     // 3
  explicit foo(char x);    // 4
};

构造函数 1 和 2 都是转换 C++03 和 C++11 中的构造函数.必须带两个参数的构造函数 3 只是 C++11 中的转换构造函数.最后一个构造函数 4 不是转换构造函数,因为它是 explicit.

Constructors 1 and 2 are both converting constructors in C++03 and C++11. Constructor 3, which must take two arguments, is only a converting constructor in C++11. The last, constructor 4, is not a converting constructor because it is explicit.

  • C++03:§12.3.1

没有函数说明符声明的构造函数,可以用单个参数调用的explicit指定从它的第一个参数的类型到它的类的类型的转换.这样的构造函数称为转换构造函数.

A constructor declared without the function-specifier explicit that can be called with a single parameter specifies a conversion from the type of its first parameter to the type of its class. Such a constructor is called a converting constructor.

  • C++11:§12.3.1

    未使用函数说明符声明的构造函数explicit 指定了从其参数类型到其类类型的转换.这样的构造函数称为转换构造函数.

    A constructor declared without the function-specifier explicit specifies a conversion from the types of its parameters to the type of its class. Such a constructor is called a converting constructor.

  • 为什么在 C++11 中将具有多个参数的构造函数视为转换构造函数?这是因为新标准为我们提供了一些方便的语法,用于使用 braced-init-lists 传递参数和返回值.考虑以下示例:

    Why are constructors with more than a single parameter considered to be converting constructors in C++11? That is because the new standard provides us with some handy syntax for passing arguments and returning values using braced-init-lists. Consider the following example:

    foo bar(foo f)
    {
      return {1.0f, 5};
    }
    

    将返回值指定为 braced-init-list 的能力被认为是一种转换.这使用了 foo 的转换构造函数,它接受一个 float 和一个 int.另外,我们可以通过bar({2.5f, 10})来调用这个函数.这也是一种转换.由于它们是转换,因此它们使用的构造函数转换构造函数是有意义的.

    The ability to specify the return value as a braced-init-list is considered to be a conversion. This uses the converting constructor for foo that takes a float and an int. In addition, we can call this function by doing bar({2.5f, 10}). This is also a conversion. Since they are conversions, it makes sense for the constructors they use to be converting constructors.

    因此,重要的是要注意,使 foo 的构造函数采用 floatint 具有 显式 函数说明符会阻止上面的代码编译.上面的新语法只有在有一个转换构造函数可以完成这项工作时才能使用.

    It is important to note, therefore, that making the constructor of foo which takes a float and an int have the explicit function specifier would stop the above code from compiling. The above new syntax can only be used if there is a converting constructor available to do the job.

    • C++11:§6.6.3:

    带有 braced-init-list 的 return 语句通过复制列表初始化 (8.5.4) 来初始化要从函数返回的对象或引用指定的初始化列表.

    A return statement with a braced-init-list initializes the object or reference to be returned from the function by copy-list-initialization (8.5.4) from the specified initializer list.

    §8.5:

    在参数传递 [...] 中发生的初始化 [...] 称为复制初始化.

    The initialization that occurs [...] in argument passing [...] is called copy-initialization.

    §12.3.1:

    显式构造函数像非显式构造函数一样构造对象,但仅在显式使用直接初始化语法 (8.5) 或强制转换 (5.2.9, 5.4) 的情况下才会这样做.

    An explicit constructor constructs objects just like non-explicit constructors, but does so only where the direct-initialization syntax (8.5) or where casts (5.2.9, 5.4) are explicitly used.

    相关文章