容易令人迷惑的构造函数
5、使用explicit禁止隐式类型转换
在构造函数的前面加上explicit就可以避免构造函数被自动匹配为转换构造函数,从而避免了隐式类型转换。
比较下面两个例子:
#define _CRT_SECURE_NO_DEPRECATE 1
//design by ajk
#include <iostream>
using namespace::std;
class Student{
public:
Student(char const *ptrName = "", int id = 0):m_id(id){
ptrName = ptrName ? ptrName:"";
m_sPtrName = new char[strlen(ptrName)+1];
strcpy(m_sPtrName, ptrName);
cout << "Constructing NEW student "
<< m_sPtrName
<< ", id is "
<< m_id << endl;
}
Student(Student const &s){
char *prefix = "COPY OF ";
size_t length = strlen(s.m_sPtrName) + strlen(prefix) + 1;
m_sPtrName = new char[length];
strcpy(m_sPtrName, prefix);
strcat(m_sPtrName, s.m_sPtrName);
m_id = s.m_id;
cout << "Constructing student "
<< m_sPtrName
<< ", id is "
<< m_id << endl;
}
~Student(){
cout << "Destructing the student "
<< m_sPtrName
<< ", id is "
<< m_id << endl;
delete []m_sPtrName;
}
Student& operator=(Student const &s){
char *prefix = "ASSIGNED FROM ";
size_t length = strlen(s.m_sPtrName) + strlen(prefix) + 1;
if(length != strlen(m_sPtrName)+1){
delete []m_sPtrName;
m_sPtrName = new char[length];
}
strcpy(m_sPtrName, prefix);
strcat(m_sPtrName, s.m_sPtrName);
m_id = s.m_id;
cout << "Assigned the student "
<< m_sPtrName
<< ", id is "
<< m_id << endl;
return *this;
}
void GetInfo(){
cout << "Get Info: The Student is "
<< m_sPtrName
<< ", id is "
<< m_id << endl;
}
private:
char *m_sPtrName;
int m_id;
};
Student Func(Student s){
cout << "In the Func()" << endl;
s.GetInfo();
cout << "Leaving the Func()" << endl;
return s;
}
int main(){
Student s1("ajk", 1);
s1 = "Tony";
cout << "Back in main()" << endl;
}
在这个例子中,构造函数没有加explicit属性,所以”Tony”这个字符串会自动去匹配转换构造函数,实现隐式转换。
输出结果为:
Constructing NEW student ajk, id is 1
Constructing NEW student Tony, id is 0
Assigned the student ASSIGNED FROM Tony, id is 0
Destructing the student Tony, id is 0
Back in main()
Destructing the student ASSIGNED FROM Tony, id is 0
下面的例子中,在构造函数加上了的explicit
#define _CRT_SECURE_NO_DEPRECATE 1
//design by ajk
#include <iostream>
using namespace::std;
class Student{
public:
explicit Student(char const *ptrName = "", int id = 0):m_id(id){
ptrName = ptrName ? ptrName:"";
m_sPtrName = new char[strlen(ptrName)+1];
strcpy(m_sPtrName, ptrName);
cout << "Constructing NEW student "
<< m_sPtrName
<< ", id is "
<< m_id << endl;
}
Student(Student const &s){
char *prefix = "COPY OF ";
size_t length = strlen(s.m_sPtrName) + strlen(prefix) + 1;
m_sPtrName = new char[length];
strcpy(m_sPtrName, prefix);
strcat(m_sPtrName, s.m_sPtrName);
m_id = s.m_id;
cout << "Constructing student "
<< m_sPtrName
<< ", id is "
<< m_id << endl;
}
~Student(){
cout << "Destructing the student "
<< m_sPtrName
<< ", id is "
<< m_id << endl;
delete []m_sPtrName;
}
Student& operator=(Student const &s){
char *prefix = "ASSIGNED FROM ";
size_t length = strlen(s.m_sPtrName) + strlen(prefix) + 1;
if(length != strlen(m_sPtrName)+1){
delete []m_sPtrName;
m_sPtrName = new char[length];
}
strcpy(m_sPtrName, prefix);
strcat(m_sPtrName, s.m_sPtrName);
m_id = s.m_id;
cout << "Assigned the student "
<< m_sPtrName
<< ", id is "
<< m_id << endl;
return *this;
}
void GetInfo(){
cout << "Get Info: The Student is "
<< m_sPtrName
<< ", id is "
<< m_id << endl;
}
private:
char *m_sPtrName;
int m_id;
};
Student Func(Student s){
cout << "In the Func()" << endl;
s.GetInfo();
cout << "Leaving the Func()" << endl;
return s;
}
int main(){
Student s1("ajk", 1);
s1 = "Tony"; //Error,由于有explicit,所以不能进行隐式转换
cout << "Back in main()" << endl;
}
构造函数被加上explicit属性后,就不能被自动匹配为转换构造函数,所以这里的字符串”Tony”不能进行隐式类型转换。类型不匹配导致编译不能通过。