所谓类的隐式转换,就是将实参类型转成形参类型--如果不一致的话。
这个转换与基本类型转换不太一样,具体则是在形参类型的构造函数中使用实参类型的数据,从而构造出一个临时对象。
下面的代码,类Person 的成员函数 isSamePerson(const Person &person) const ,理论上需要一个 Person 引用,但实际上被传递了一个 string对象!
编译器会自动调用 Person tmp(str)构造函数 来构造一个临时对象,而不是真的将 string类型 转成 Person 类型!
代码:
#include <iostream> #include <string> using namespace std; class Person{ private: string name; int id; public: Person(const string &nm=string("xxx")):name(nm),id(0){} //就不用默认无参构造了 ;隐式转换 public: bool isSamePerson (const Person &person) const{ //const成员函数 ,只能调用const成员(变量、函数)! cout<<"比较对象:"<<person.getId()<<"--"<<person.getName()<<endl;// return id == person.getId(); // } const int &getId() const{ //任意一个const去掉后,都会导致问题。。。 return id; } const string &getName() const{ //因为const修饰的是this指向的对象,所以也必须返回const引用 return name; } }; int main(){ string a="aaa"; Person p1(a); cout<<p1.getId()<<"--"<<p1.getName()<<endl; string b="bbb"; cout<<p1.isSamePerson(b)<<endl; //隐式转换!!! return 0; }
尽管有时候这样的转换是我们需要的,但也有不需要的时候,这个时候,给类中的构造函数声明加上explicit,则会防止在需要隐式转换的上下文中使用该构造函数。
#include <iostream> #include <string> using namespace std; class Person{ private: string name; int id; public: explicit Person(const string &nm=string("xxx")):name(nm),id(0){} //就不用默认无参构造了 ;显式 explicit public: bool isSamePerson (const Person &person) const{ //const成员函数 cout<<"比较对象:"<<person.getId()<<"--"<<person.getName()<<endl;// return id == person.getId(); // } const int &getId() const{ //任意一个const去掉后,都会导致问题。。。 return id; } const string &getName() const{ //因为const修饰的是this指向的对象,所以也必须返回const引用 return name; } }; int main(){ string a="aaa"; Person p1(a); cout<<p1.getId()<<"--"<<p1.getName()<<endl; string b="bbb"; cout<<p1.isSamePerson(Person(b))<<endl;//显式转换!!! return 0; }
结论:除非有明显的理由想要使用隐式转换,否则,单形参的构造函数应该设置为explicit 。
其他:前向声明只能用于使用指针或引用的情况。