C++类的 explicit 关键字和隐式转换
explicit 关键字用于 C++的类定义中,其作用是禁止隐式转换和复制初始化操作:
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.
这里介绍一个概念:转换构造函数, 它的英文定义如下:
A constructor with a single non-default parameter (until C++11) that
is declared without the function specifier explicit is called a
converting constructor.
大意就是说不用 explicit 关键字声明, 只包含一个非默认参数的构造函数.
具体使用用一个例子来说明:
#include <iostream>
using std::cout;
struct A
{
A(int) { cout << "A(int)\n"; } // converting constructor
A(int, int) { cout << "A(int, int)\n"; } // converting constructor (C++11)
A(const A&) {cout << "A(const A&)\n";}
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; // copy-initialization, call A(int)
A a2(2); // direction-initialization, call A(int)
A a3 {4, 5}; //direction-list-initialization, call A(int int)
A a4 = {4, 5};//copy-list-initialization, call A(int int)
A a5 = (A)1; //explicit cast
if(a1) //copy-initializat, call operator bool
cout << "true\n";
bool na1 = a1;
cout << std::boolalpha << na1 << '\n';
bool na2 = static_cast<bool>(a1);
cout << std::boolalpha << na2 << '\n';
//B b1 = 1; //no viable conversion from 'int' to 'B'
B b2 = (B)1;
B b3(2);
B b4 {4, 5};
//B b5 = {4, 5};//chosen constructor is explicit in copy-initialization
if(b2)
cout << "true\n";
//bool nb1 = b2;//no viable conversion from 'B' to 'bool'
bool nb1 = b2.operator bool();
bool nb2 = static_cast<bool>(b2);
}
上例中选用了两个 struct, 这里出于使用方便, 你完全可以可用 class, 不过需要使用 public 声明成员函数. A 中没有使用 explicit 关键字, 所以对于 A 隐式转换和复制初始化都可以顺利进行, 但是与之相对 B 由于使用了 explicit 声明, 隐式转换和复制初始化被禁止.
B b1 = 1;
//no viable conversion from 'int' to 'B'
B b2 = (B)1; //explicit conversion
B b5 = {4, 5};
//chosen constructor is explicit in copy-initialization
bool nb1 = b2;
//no viable conversion from 'B' to 'bool'
bool nb1 = b2.operator bool();
这时, 我们或可以强制进行类型转换, 也可显示调用转换函数