15.10 选择一个转换


用户定义的转换包括调用转换函数,或者调用构造函数

class Number{
public :
operator float();
operator int();
//...
};
Num num;
float ff = num //调用operator float()函数。

因为:
operator float() ->精确匹配
operator int() ->标准转换
精确匹配优于标准转换

 

两个构造函数都能把一个值变成转换的目标类型,如:

class SmallInt{
public :
SmallInt(int val):val(val){}
SmallInt(double dval)
:value(static_cast<int>     (dval)){}
//...
}
extern vodi manip(const SmallInt &);
int main(){
double dobj;
manip(dobj); //这里调用SamllInt(double)
}

SmallInt(double)属于精确匹配
SmallInt(int) 属于标准匹配


当执行一完成一个用户定义转换序列后,再执行一个标准准换,
有可能出现问题,如:

class Number{
public:
operator float();
operator int();
//...
}
Number num;
long lval =num; //错误,二义性

 

operator float() ->标准转换
operator int()->标砖转换
两种转换是一样的,编译器无法选择出更优的选择,不过可以指定强转换来指定,如:

long lval = static_cast<int>(num);将调用Number::operator int()转换函数

 

在为隐式转换选择一个用户定义的转换序列时,如果这两个类定
义了互相转换的函数,可能出现二义性,如:

class SmallInt{
public:
SmallInt(const Number&);
//...
}
class Number{
public:
operator SamllInt();
//...
}
extern void compute(SmallInt);
extern void Number num;
compte(num); //错误,两个可能的转换

num转换成SmallInt对象,可以通过构造函数来转换,也可以通过
转换函数来转换,这两种方式都属于用户定义的转换,优先级别
是一样的。
可以通过显示调用来解决,如:
compute(num.operator SmallInt());//显示调用解决二义性问题


15.10.2候选函数

当函数调用的实参是类类型,指向类类型的指针或者是指向成员
的指针,需要为该调用考虑一个很大的函数集,作为候选函数。

Namespace NS{
class SmallInt{
friend SmallInt add(SmallInt,int){//...}
};
class String{//...};
String add(const String &,const String &);
}
const matrix& add(const matrix &,int);
double add(double,double);
int main(){
NS::SmallInt si(15);
add(si,566); //调用友元函数
return 0;
}

候选函数:
1.全局函数
add(const matrix &,int)
add(double,double)
2.名字空间函数
NS::add(const String &,const String &)
3.友元函数
NS::add(SmallInt ,int)
重载函数选择友元函数作为最佳匹配函数,因为友元函数的两个
实参是精确匹配

 

15.10.3 类域中的函数所调用的候选函数

namespace NS{
struct myClass{
void k(int);
static void k(char*);
void mf();
};
int k(double);
};

void h(char);
void NS::myClass::mf(){
h('a'); //调用全局h(char)
k(4); //调用myClass::k(int)
}

函数调用在查找过程中,一旦找到了函数声明,则查找在调用点
可以见的候选函数,找到,则退出查找过程。


15.10.4对用户定义的转换序列化分等级

class SmallInt{
public SmallInt(int);
};
extern void calc(double);
extern void calc(SmallInt);
int ival;
int main(){
calc(ival); //调用calc(double);
}

当用户定义的转换与标准转换都可行时,优先考虑标准转换。
如果两个转换都是用户定义的转换,则无法判断优先级,程序出现二义性,如:

class Number{
public:
operator SmallInt();
operator int();
};
extern void calc(int);
extern void calc(SmallInt);
extern Number num;
clac(num); //错误,二义性

Number对象定了两个转换函数,这两个转换函数具有相同的优先级。可以显示指定来解决二义性,如
calc(static_cast<int>(num)); //调用int()转换函数
calc(static_cast<SmallInt>(num)); //调用SmallInt()转换函数

如果Number中没有Int(),调用calc(num)还是二义的吗?
也是二义的,虽然SmallInt可以再次转换的Int型,但是在转换过程中,只能存在一个用户定义的转换,如果Number对象先转换成SmallInt对象,SmallInt对象再转换成Int对象,存在两次用户定义的转换。

 

 

 

 

 

 

 

posted on 2013-08-07 10:42  CQU  阅读(192)  评论(0编辑  收藏  举报

导航