给构造函数声明 explicit
可以阻止它们被用来执行隐式类型转换(implicit type conversions),例如对于下面的代码:
using namespace std;
class Student {
public:
int id, score;
Student(int id = 0, int score = 0) : id(id), score(score) {}
};
void display(Student s) {
cout << "ID: " << s.id
<< ", Score: " << s.score << endl;
}
int main() {
display(1);
Student s = 1;
cout << "ID: " << s.id
<< ", Score: " << s.score << endl;
return 0;
}
我们定义了一个 Student
类,然后构造函数没有用 scplicit
声明,该类有两个变量,分别是学生的学号 id
和分数 score
,并且都有默认值 0. 还定义了一个函数 display
来打印出 Student
类的两个变量。
在 main
函数中我们调用 display(1)
,按照函数的定义,应该是传入一个 Student
类的,但是现在是传入一个整数 1,按道理应该不是正确的用法,正确的用法应该是 display(Student(1))
。对于 Student s = 1;
直接将整数 1 赋值给一个 Student
类,按道理也应该是不正确,正确的应该是 Student s(1)
。
但是这个代码可以编译并且成功运行,并且输出:ID: 1, Score: 0
。
这就是发生了隐式类型转换。如果给构造函数前面加上 explicit
关键字声明,类定义变成:
using namespace std;
class Student {
public:
int id, score;
explicit Student(int id = 0, int score = 0) : id(id), score(score) {}
};
其他的不变,只是第 6 行加了一个 explicit
,那么就会编译不通过。因为这个时候就无法进行隐式类型转换。
将 main
函数重新写成这样:
int main() {
display(Student(1));
Student s(1);
cout << "ID: " << s.id
<< ", Score: " << s.score << endl;
return 0;
}
就可以编译通过正常执行,并且输出:ID: 1, Score: 0
。