隐式VS显式转换 [英] Implicit VS Explicit Conversion

查看:273
本文介绍了隐式VS显式转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



之间有一点小小的区别

  X x; 
Y y(x)//显式转换

$ b b

  X x; 
Y y = x; //隐式转换

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



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



在这两种情况下如何处理转换,什么使得它显式/隐式,以及如何绑定到一个类构造函数定义与显式关键字,如果有?


$ b $


b

没有。在第二种情况下,它不是赋值,它是一个初始化,赋值运算符( operator = )从不被调用;而是调用非< - code>显式单参数构造函数(接受类型 X 作为参数)。



初始化和赋值之间的区别很重要:在第一种情况下,正在创建一个新对象,并且它的初始化值因此为什么会调用构造函数),而当对象被分配(〜复制)给已经存在的对象并且已经处于确定状态时, p>

无论如何,你写的两种形式的初始化不同的事实,在第一种情况下,你显式调用一个构造函数,因此任何构造函数都是可以接受的;在第二种情况下,由于您不使用经典构造函数语法,而是使用初始化语法,因此您正在调用构造函数



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



如指定在此另一个答案,任何未标记为显式的构造函数可以参与对eg的隐式转换将传递给函数的对象转换为该函数期望的类型。实际上,你可能会说,这是你的第二个例子:你想初始化(=创建一个值从其他地方复制) y x ,但是 x 首先必须转换为 Y 隐式构造函数。



这种隐式转换通常是可取的:例如对于一个有转换的字符串类(即非 - / code>)构造函数从 const char * :接收 string 参数的任何函数也可以使用正常C字符串调用:因为转换构造函数调用者将使用C字符串,被调用者将收到其 string 对象。



然而,在某些情况下,单参数构造函数可能不适合转换:通常这种情况发生时,他们的唯一参数不是概念上转换为正在创建的对象的类型,但它是只是一个参数的建设;考虑一个文件流对象的例子:可能它有一个构造函数接受要打开的文件的名称,但是说这个字符串被转换为对该文件有效的流是没有意义的。 p>

您还可以找到一些更复杂的场景,其中这些隐式转换可能完全混乱程序员期望从重载分辨率的行为;例子可以在下面我链接的答案下面找到。



更简单地说,也可能发生一些构造函数可能是非常重量级的,所以类设计器可能需要确保它们被显式调用。在这些情况下,构造函数标记为 explicit ,因此它只能在显式地作为构造函数调用时使用,并且不参与隐式转换。 p>

The C++ Standard Library by Nicolai M. Josuttis states:

There is a minor difference between

X x;
Y y(x) //explicit conversion

and

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

Following to say: "The former creates a new object of type Y by using an explicit conversion from type X, whereas the latter creates a new object of type Y by using an implicit conversion."

I'm a little confused about the concepts of explicit vs implicit conversion I guess. In both cases you're taking an X and pushing it into a Y per se - one uses a Y's constructor and one uses the assignment operator though.

What's the difference in how the conversion is treated in these two cases, what makes it explicit/implicit, and how does this tie into making a class constructor defined with the "explicit" key word, if at all?

解决方案

one uses a Y's constructor and one uses the assignment operator though.

Nope. In the second case it's not an assignment, it's an initialization, the assignment operator (operator=) is never called; instead, a non-explicit one-parameter constructor (that accepts the type X as a parameter) is called.

The difference between initialization and assignment is important: in the first case, a new object is being created, and it starts its life with the value that it is being initialized with (hence why a constructor is called), while assignment happens when an object is assigned (~copied) to an object that already exists and already is in a definite state.

Anyway, the two forms of initialization that you wrote differ in the fact that in the first case you are explicitly calling a constructor, and thus any constructor is acceptable; in the second case, you're calling a constructor implicitly, since you're not using the "classical" constructor syntax, but the initialization syntax.

In this case, only one-parameter constructors not marked with explicit are acceptable. Such constructors are called by some people "converting" constructors, because they are involved in implicit conversions.

As specified in this other answer, any constructor not marked as explicit can take part in an implicit conversion for e.g. converting an object passed to a function to the type expected by such function. Actually, you may say that it's what happens in your second example: you want to initialize (=create with a value copied from elsewhere) y with x, but x first has to be converted to type Y, which is done with the implicit constructor.

This kind of implicit conversion is often desirable: think for example to a string class that has a converting (i.e. non-explicit) constructor from a const char *: any function that receives a string parameter can also be called with a "normal" C-string: because of the converting constructor the caller will use C-strings, the callee will receive its string object.

Still, in some cases one-parameters constructors may not be appropriate for conversion: usually this happens when their only parameter is not conceptually "converted" to the type of the object being created, but it is just a parameter for the construction; think for example about a file stream object: probably it will have a constructor that accepts the name of the file to open, but it makes no sense to say that such string is "converted" to a stream that works on that file.

You can also find some more complex scenarios where these implicit conversions can completely mess-up the behavior that the programmer expects from overload resolution; examples of this can be found in the answers below the one I linked above.

More simply, it can also happen that some constructors may be very heavyweight, so the class designer may want to make sure that they are invoked explicitly. In these cases, the constructor is marked as explicit, so it can be used only when called "explicitly as a constructor" and doesn't take part in implicit conversions.

这篇关于隐式VS显式转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆