C++-auto关键词

引入

C++类的实例化过程中,存在一种隐式转换,即可以用单个实参来调用的构造函数定义了从形参类型到该类类型的一个隐式转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Person
{
private:
string _name;
public:
Person() {}
Person(const string name) : _name(name)
{
cout << "构造函数调用!" << endl;;
};
void IsSameOne(const Person& book)
{
if (_name == book._name)
cout << "两个人重名!" << endl;
else
cout << "两个人不重名!" << endl;
}
};

int main()
{
Person Tom("Tom");
Tom.IsSameOne(string("Tom"));
return 0;
}
/* 输出如下
* 构造函数调用!
* 构造函数调用!
* 两本书重名!
*/

此时的第一次输出构造函数是在构造对象 Tom 时调用的,而第二次构造则是通过string类型的 “Tom” 作为IsSameOne的形参时发生的,这个函数的形参本该是一个 Person 的类对象,而 Person 类又满足构造函数**只含有一个未初始化的形参的条件(也可以含有多个已经初始化的形参)**。所以这里编译器进行了一次隐式转换,把 “Tom” 作为形参,实例化了一个 Person 类的临时对象。这样,对象 Tom 就和这个对象判断是否名字一样,然后在函数结束时销毁。

如何解决

而为了防止这种情况的发生,在类的构造函数前加上explicit关键词,可以防止形参隐式转换为该类型的转换发生。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Person
{
private:
string _name;
public:
Person() {}
explicit Person(const string name) : _name(name)
{
cout << "构造函数调用!" << endl;;
};
void IsSameOne(const Person& book)
{
if (_name == book._name)
cout << "两个人重名!" << endl;
else
cout << "两个人不重名!" << endl;
}
};

int main()
{
Person Tom("Tom");
Tom.IsSameOne(string("Tom"));// error!不存在用户定义的从 "std::string" 到 "const Person" 的适当转换。
// 应该这样做
Person SameTom = Person("Tom");
Tom.IsSameOne(SameTom);
return 0;
}

在添加explicit关键词后,使用Tom.IsSameOne(string("Tom"))时,编译器会报错。explicit关键词可以防止隐式转换的发生,但是仍可以使用显示转换,如Person SameTom = Person("Tom")