概述
What does the explicit keyword in C++ mean?
In C++, the compiler is allowed to make one implicit conversion to resolve the parameters to a function. What this means is that the compiler can use constructors callable with a single parameter to convert from one type to another in order to get the right type for a parameter.
Here’s an example class with a constructor that can be used for implicit conversions:
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;
};
Here’s a simple function that takes a Foo object:
void DoBar (Foo foo)
{
int i = foo.GetFoo ();
}
and here’s where the DoBar function is called.
int main ()
{
DoBar (42); // int
}
The argument is not a Foo
object, but an int
. However, there exists a constructor for Foo
that takes an int , so this constructor can be used to convert the parameter to the correct type.
The compiler is allowed to do this once for each parameter.
Prefixing the explicit keyword to the constructor prevents the compiler from using that constructor for implicit conversions. Adding it to the above class will create a compiler error at the function call DoBar (42). It is now necessary to call for conversion explicitly with DoBar (Foo (42)).
The reason you might want to do this is to avoid accidental construction that can hide bugs. Contrived example:
You have a MyString(int size) class with a constructor that constructs a string of the given size. You have a function print(const MyString&), and you call it with print(3). You expect it to print “3”, but it prints an empty string of length 3 instead.
设想示例:
你有一个MyString(int size)类,构造函数构造给定大小的字符串。 你有一个函数print(const MyString&),你用print(3)调用它。 你希望它打印“3”,但它打印一个长度为3的空字符串。
explicit specifier
The explicit
specifier specifies that a constructor or conversion function (since C++11) doesn’t allow implicit conversions or copy-initialization. It may only appear within the decl-specifier-seq of the declaration of such a function within its class definition.
Notes
具有单个非默认参数(直到C ++ 11)的构造函数, 没有explicit函数说明符,称为转换构造函数
A constructor with a single non-default parameter (until C++11) that is declared without the function specifier explicit is called a converting constructor.
Both constructors (other than copy/move) and user-defined conversion functions may be function templates; the meaning of explicit doesn’t change.
struct A
{
A(int) { } // converting constructor
A(int, int) { } // converting constructor (C++11)
operator bool() const { return true; }
};
struct B
{
explicit B(int) { }
explicit B(int, int) { }
explicit operator bool() const { return true; }
};
int main()
{
A a1 = 1; // OK: copy-initialization selects A::A(int)
A a2(2); // OK: direct-initialization selects A::A(int)
A a3{ 4, 5 }; // OK: direct-list-initialization selects A::A(int, int)
A a4 = { 4, 5 }; // OK: copy-list-initialization selects A::A(int, int)
A a5 = (A)1; // OK: explicit cast performs static_cast
if (a1){} // OK: A::operator bool()
bool na1 = a1; // OK: copy-initialization selects A::operator bool()
bool na2 = static_cast<bool>(a1); // OK: static_cast performs direct-initialization
// B b1 = 1; // error: copy-initialization does not consider B::B(int)
B b2(2); // OK: direct-initialization selects B::B(int)
B b3{ 4, 5 }; // OK: direct-list-initialization selects B::B(int, int)
// B b4 = {4, 5}; // error: copy-list-initialization does not consider B::B(int,int)
B b5 = (B)1; // OK: explicit cast performs static_cast
if (b2); // OK: B::operator bool()
// bool nb1 = b2; // error: copy-initialization does not consider B::operator bool()
bool nb2 = static_cast<bool>(b2); // OK: static_cast performs direct-initialization
}
this keyword is a declaration specifier that can only be applied to in-class constructor declarations. An explicit constructor cannot take part in implicit conversions. It can only be used to explicitly construct an object.
只能应用于类的构造函数声明。 显式构造函数不能参与隐式转换。 它只能用于显式构造一个对象。
Implicit VS Explicit Conversion
X x;
Y y(x) //explicit conversion
X x;
Y y = x; //implicit conversion
在第一种情况下,你显式调用一个构造函数,因此任何构造函数是可以接受的;在第二种情况下,你隐式调用构造函数,因为你不使用“经典”构造函数语法,而是使用初始化语法。
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: 你想用x初始化y,中间用“等号”连接(you want to initialize (=create with a value copied from elsewhere) y with x),但是,x首先被转换成Y类型,这是由隐式构造函数自动完成的( 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.
最后
以上就是无限春天为你收集整理的explicit关键字的全部内容,希望文章能够帮你解决explicit关键字所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复