a. 利用构造函数自动转换
这种方法是通过构造函数把另外一个类型的对象或者引用作为参数,通过这样的方式来实现参数类型到构造类型之间的转换(好像没有表达清楚),咱们看代码:
class AC {
public:
AC() {}
};
class BC {
public:
BC( const AC& a ) { //注意构造函数的参数类型
cout << "
Invoke
BC
( const AC& a )" << endl;
}
};
void fun( BC ) { //注意函数传递的参数类型
cout << "invoke fun(BC) " << endl;
}
int main() {
AC aclass;
fun(aclass); //注意输入的参数类型
}
输出结果
Invoke BC( const AC& a )
invoke fun(BC)
显然,在调用 fun(aclass); 的时候,自动通过调用 BC的构造函数生成了BC对象,这样就可以正确使用这个函数,但是如果参数是通过引用传递的:void fun( BC& ),上诉做法就会出现错误。如果想避免出现这样的隐式调用,则使用 explicit关键字:
class BC {
public:
explict BC( const AC& a ) { //注意构造函数的参数类型
cout << "
Invoke
BC
( const AC& a )" << endl;
}
};
这样,上述的隐式转换就不会成功。
b. 利用自定义operator classname 定义转换类型
通过operator关键字创建一个成员函数,关键字后面跟上想要转换的目的类型,这样就可以实现将当前类型转换到目的类型:
class Three {
public:
Three(int sz = 0) : size(sz) {
cout << "Invoke Three(int sz = 0)" << endl;
}
private:
int size;
};
class Four {
public:
Four(int sz ): size(sz) {
cout << "Invoke Four(int sz )" << endl;
}
operator Three() const {
cout << "Invoke Four::operator Three() " << endl;
return Three(size);
//由于类 Three 和 类 Four之间的关联性,它们之间的转换是可行的
}
private:
int size;
};
void fun( Three ) { //注意函数传递的参数类型 同样参数不可以是引用
cout << "invoke fun(Three) " << endl;
}
int main() {
Four four(1);
fun(four); //通过调用 operator Three() 进行类型转换
fun(1); //同样是自动类型转换,通过构造函数 从 int 到 Three
}
输出结果:
Invoke Four(int sz )
Invoke Four::operator Three()
Invoke Three(int sz = 0)
invoke fun(Three)
Invoke Three(int sz = 0)
invoke fun(Three)
显然通过自定义的operator Three() 实现了由 Three 到 Four之间的转换。
自动类型转换的问题:
自动类型转换由于是由编译器隐式调用的,有很多细节我们不是很清楚,在使用这个功能的时候要格外小心,下面两种情况会出现问题:(copy from thinking in c++)
class
Orange
; //class declaration
class Apple {
public:
operator Orange() const {} //自定义转换
};
class
Orange
{
public:
Orange(Apple); //构造转换
};
void fun(
Orange
) {}
int main() {
Apple ap;
// fun (a); //狂晕,到底是调用Apple::operator
Orange
()
//还是Orange::Orange(Apple),显然,编译器会认为有冲突
}
还有,当类自定义了到多个类型的转换时,就不能进行下面的重载:
class
Orange
{}; //class declaration
class Pear {};
class Apple {
public:
operator Orange() const {} //自定义转换
operator Pear() const {] //另外一个转换
};
//重载fun
void fun(
Orange
) {}
void fun(Pear) {}
int main() {
Apple ap;
// fun(a); //实在狂晕,到底是调用想怎么转换
//不论怎么转换,都使得fun的重载是错误的
}
很明显,自动类型转换不是太好用的东东,我们必须在确定需要它的时候在使用它,而且必须确保无误,否则会很难调试,待续...
|