隐式VS显式转换

时间:2011-08-17 21:49:02

标签: c++ type-conversion

Nicolai M. Josuttis的C ++标准库声明:

之间存在细微差别
X x;
Y y(x) //explicit conversion

X x;
Y y = x; //implicit conversion

接下来说:“前者通过使用类型X的显式转换创建Y类型的新对象,而后者通过使用隐式转换创建类型为Y的新对象。”

我猜对于显式与隐式转换的概念我有点困惑。在这两种情况下,你都使用X并将其推入Y本身 - 一个使用Y的构造函数,一个使用赋值运算符。

在这两种情况下如何处理转换有什么不同,是什么使它显式/隐式,以及如何使用“显式”关键字定义类构造函数(如果有的话)?

4 个答案:

答案 0 :(得分:28)

  

一个使用Y的构造函数,但是一个使用赋值运算符。

不。在第二种情况下,它不是赋值,它是初始化,从不调用赋值运算符(operator=);相反,调用非explicit单参数构造函数(接受类型X作为参数)。

初始化和赋值之间的区别很重要:在第一种情况下,正在创建一个新对象,并且它以其初始化的值开始其生命(因此调用构造函数的原因),而赋值发生时将对象分配(〜复制)到已存在的对象并且已处于明确状态的对象时。

无论如何,您编写的两种初始化形式的不同之处在于,在第一种情况下,您显式调用构造函数,因此任何构造函数都是可接受的;在第二种情况下,你正在隐式地调用构造函数 ,因为你没有使用“经典”构造函数语法,而是初始化语法。

在这种情况下,只有未标记explicit的单参数构造函数是可接受的。这些构造函数被一些人称为“转换”构造函数,因为它们涉及隐式转换。

根据指定的in this other answer,任何未标记为explicit的构造函数都可以参与隐式转换,例如将传递给函数的对象转换为此函数所期望的类型。实际上,你可能会说这是你的第二个例子中发生的事情:你想初始化(=使用从其他地方复制的值创建)y x,但x首先必须是转换为类型Y,这是使用隐式构造函数完成的。

这种隐式转换通常是可取的:例如,假设一个字符串类具有来自explicit的转换(即非const char *)构造函数:任何接收{{1}的函数也可以使用“普通”C字符串调用参数:由于转换构造函数调用者将使用C字符串,被调用者将接收其string对象。

但是,在某些情况下,单参数构造函数可能不适合转换:通常,当它们的唯一参数在概念上“转换”为正在创建的对象的类型时会发生这种情况,但它只是构造的参数;例如,想一个文件流对象:可能它会有一个构造函数接受要打开的文件的名称,但是说这样的字符串被“转换”为适用于该文件的流是没有意义的。

您还可以找到一些更复杂的场景,其中这些隐式转换可以完全搞砸程序员期望从重载解析的行为;这个例子可以在我上面链接的答案中找到。

更简单的是,也可能发生一些构造函数可能非常重量级,因此类设计者可能希望确保明确调用它们。在这些情况下,构造函数标记为string,因此只有在“显式地作为构造函数”调用时才能使用它,并且不参与隐式转换。

答案 1 :(得分:3)

第一种形式是直接初始化。第二个是复制初始化

复制初始化隐式调用转换构造函数或转换运算符,然后显式调用复制构造函数(可以省略复制构造函数调用,但仍必须执行辅助功能检查)。

考虑第三种可能性,即复制初始化,但转换是显式的:

Y y = Y(x);

Y y = (Y)x;

答案 2 :(得分:2)

  

虽然使用赋值运算符

不,它没有。它直接调用构造函数。

一个是显式的而一个是隐式的原因是因为隐式转换可能在您不希望它们发生时发生。明确的不能。最简单的例子是布尔。

假设你发明了一些可以是真或假的类型 - 就像指针一样。然后让我们进一步说你决定为了让用户的生活更轻松,你可以让它隐含地转换为bool。这很好 - 直到你的一个用户做了一些愚蠢的事情。

int i = 0;
i = i >> MyUDT();

哦等等 - 为什么会编译?你根本无法改变MyUDT!它编译是因为bool是一个整数类型。编译器隐式地将它转换为bool,然后转换为可以移位的东西。上面的代码显然是愚蠢的 - 我们只希望人们能够转换为 bool ,而不是bool以及bool可能想要做的任何事情。

这就是将显式转换运算符添加到C ++ 0x的原因。

答案 3 :(得分:0)

隐式投射并不需要任何投射操作符。当将数据从较小的整数类型转换为较大的或派生类型到基本类型时,通常使用此转换。

int iVal = 100;     double dVal = iVal;

显式转换构造函数优先于隐式转换运算符,因为在后一种情况下,还会对复制构造函数进行额外调用。Implicit and Explicit converstions