转换用户定义的类类型,必须由用户告知。用户告知的方式就是定义含一个参数的构造函数。
例如,下面的代码中定义了学生类的构造函数:
class Student
{
public:
Student(char*);
};
void fn(Student s);
int main()
{
fn("Jenny");
return 0;
}
这里Student(char*)构造函数同时也在告知,如何将char*转换成一个Student对象。如果有重载函数fn(char*),则调用fn("Jenny")马上匹配了事。但就是因为没有这样的重载函数,所以C++对所有fn函数进行类型转换试探,包括构造函数。
因为为Student(char*)的构造函数,又有fn(Student& s)函数,于是fn("Jenny")便被认为是fn(Student("Jenny")),最终予以匹配。把构造函数用来从一种类型转换为另一种类型,这是C++从类机制中获得的附加性能。但要注意下面两点:
(1)只会尝试含有一个参数的构造函数;
(2)如果有二义性,则放弃尝试。例如:
class Student
{
public:
Student(char* pName = "no name");
};
class Teacher
{
public:
Teacher(char* pName = "no name");
};
void addCourse(Student s);
void addCourse(Teacher t);
int main()
{
addCourse("Prof.Dingleberry"); // error:二义性
return 0;
}
改正的方法是,只要显式转换一下:
addCourse(Teacher("Prof.Dingleberry"));
一个类型转换函数的例子:
#include <iostream.h>
class date
{
public:
date(int a, int b);
operator int();//类型转换函数
void output(void);
date &operator=(int);//重载等号运算符
private:
int str;
int mimg;
};
date::date(int a, int b) //构造函数
{ str = a;
mimg = b;
}
date::operator int() //类型转换函数,将date类型转换为int类型
{
return str;
}
void date::output(void)
{
cout << str << " " << mimg << endl;
return;
}
date &date::operator=(int i)
{
str=i;
mimg=1000;
return *this;
}
int main(void)
{
date da(100, 200);
date c(0,0);
//int c;
c = 55 + da;
c.output();//结果为 155 1000
//cout<<c;//结果为 155
return 0;
}
其中main函数中的c = 55 + da;若定义c为int型(如注释),则编译器首先判断等号左端的c为int类型,则须将等号右端的da用类型转换函数转换为int型,然后相加,返回int型结果。若定义c为date类型,则须将等号右端的55+da转换为date类型,但是又没有转换构造函数把常量55转为date型,也没有重载+号运算符,只能用类型转换函数将da转为int型,55+da的结果就是一个int型。但等号右端的c却为date型,等号两端类型不匹配,所以就通过重载的=号运算符,隐式调用c.operator(55+100),由于重载的=号运算符返回是一个引用类型,所以c.operator(55+100)的结果就是还是date类型的c。本程序中的c = 55 + da的调用过程是:c.operator(55+(da.operator int())).
再写一个转换构造函数的例子
#include <iostream.h>
class date
{
public:
date(int a, int b);
date(int n); //转换构造函数
friend date operator+(const date &,const date &); //重载 +
void output(void);
date &operator=(int);
private:
int str;
int mimg;
};
date::date(int a, int b) //构造函数
{ str = a;
mimg = b;
}
date :: date(int n) //转换构造函数
{
str = n;
mimg = 0;
}
date operator +(const date &a,const date &b) //重载 +
{
return date(a.str + b.str, a.mimg + b.mimg);
}
void date::output(void)
{
cout << str << " " << mimg << endl;
return;
}
int main(void)
{
date da(100, 200);
date c(0,0);
c = 55 + da;
c.output();
return 0;
}
main函数在执行c=55+da时,判断c为date类型,所以(55+da)也应为data类型。通过转换构造函数将根据55,创建一个date类型的一个临时对象,然后通过+号运算符重载函数,计算da与临时对象的和。但这里需要注意,+号运算符重载函数里的参数必须是const类型。因为非const的引用只能绑定同类型的对象,const则可以绑定能互相转换的类型。即隐式转换不会被用于非const的引用参数。
一个二义性的例子:
#include <iostream.h>
class date
{
public:
date(int a, int b);
date(int n); //转换构造函数
operator int(); //类型转换函数
friend date operator+(const date &,const date &); //重载 +
void output(void);
date &operator=(int);
private:
int str;
int mimg;
};
date::date(int a, int b) //构造函数
{ str = a;
mimg = b;
}
date :: date(int n) //转换构造函数
{
str = n;
mimg = 0;
}
date::operator int() //类型转换函数
{
return str;
}
date operator +(const date &a,const date &b) //重载 +
{
return date(a.str + b.str, a.mimg + b.mimg);
}
void date::output(void)
{
cout << str << " " << mimg << endl;
return;
}
int main(void)
{
date da(100, 200);
date c(0,0);
c = 55 + da;
c.output();
return 0;
}
如果写成这样,那么main函数在执行c=55+da的时候就会出现二义性,不知道该调用类型转换函数还是调用转换构造函数了。