12.3 转换

12.3 转换

1、类对象的类型转换可由构造函数和转换函数指定。这些转换称为用户定义的转换,可用于隐式类型转换(第4章)、初始化(8.5)和显式类型转换(5.45.2.9)。

2、只有不存在歧义(10.212.3.2)的时候才能使用用户定义的转换。转换遵从访问控制规则(第11章)。访问控制在歧义消解(3.4)之后应用。

3[注:有关转换在函数调用中的使用可参见13.3和下面的例子。]

4、最多只能有一个用户定义的转换(构造函数或转换函数)能隐式地应用于单个值。例如:

class X {

// ...

public:

operator int();

};

class Y {

// ...

public:

operator X();

};

Y a;

int b = a;      // error:

// a.operator X().operator int() not tried

int c = X(a);   // OK: a.operator X().operator int()

5、仅当不存在歧义的时候才能隐式地使用用户定义的转换。派生类中的转换函数并不能隐藏基类的转换函数,除非两个函数转换到相同的类型。函数重载解析(13.3.3)选择最好的转换函数执行转换。例如:

class X {

public:

// ...

operator int();

};

 

class Y : public X {

public:

// ...

operator char();

};

 

void f(Y& a)

{

if (a) {    // ill-formed:

// X::operator int() or Y::operator char()

// ...

}

}

12.3.1 通过构造函数的转换

1、没有使用函数说明符explicit声明,且能通过单个参数调用的构造函数定义了一个从构造函数的第一个参数类型到其所属类类型的转换。这样的构造函数称为转换构造函数。例如:

class X {

// ...

public:

X(int);

X(const char*, int =0);

};

 

void f(X arg)

{

X a = 1;                // a = X(1)

X b = "Jessie";      // b = X("Jessie",0)

a = 2;                    // a = X(2)

f(3);                     // f(X(3))

}

2、显式构造函数以非显式构造函数同样的方式构造对象,但它仅在有直接初始化成分(8.5)或显式转型(5.2.95.4)的时候才被触发。缺省构造函数可以是显式构造函数,这样的构造函数将被用于执行缺省初始化或值初始化(8.5)。例如:

class Z {

public:

explicit Z();

explicit Z(int);

// ...

};

 

Z a;                                    // OK: default-initialization performed

Z a1 = 1;                             // error: no implicit conversion

Z a3 = Z(1);                        // OK: direct initialization syntax used

Z a2(1);                              // OK: direct initialization syntax used

Z* p = new Z(1);                 // OK: direct initialization syntax used

Z a4 = (Z)1;                        // OK: explicit cast used

Z a5 = static_cast<Z>(1);     // OK: explicit cast used

3、非显式拷贝构造函数(12.8)是一种转换构造函数。隐式声明的拷贝构造函数不是显式构造函数;它只能作为隐式类型转换调用。

12.3.2 转换函数

1、名字形式如下的类X成员函数

conversion-function-id:

operator conversion-type-id

 

conversion-type-id:

type-specifier-seq conversion-declaratoropt

 

conversion-declarator:

ptr-operator conversion-declaratoropt

定义了一个从Xconversion-type-id所指定类型的转换。这样的函数称为转换函数。类、枚举和类型定义名不能在type-specifier-seq中声明。既不能给转换函数指派参数类型,也不能给转换函数指派返回类型。转换函数(8.3.5)的类型是“返回conversion-type-id的无参函数”。转换函数不能将(可能cv限定的)对象转换为(可能cv限定的)与之相同的对象类型,或(可能cv限定的)那个类型的基类(或引用),或(可能cv限定的)void

2、例如:

class X {

// ...

public:

operator int();

};

 

void f(X a)

{

int i = int(a);

i = (int)a;

i = a;

}

在上述三种情况下,所有的赋值操作都通过X::operator int()转换。

3、用户定义的转换函数并不限于赋值和初始化。例如:

void g(X a, X b)

{

int i = (a) ? 1+a : 0;

int j = (a&&b) ? a+b : i;

if (a) { // ...

}

}

4conversion-type-id不能表示函数类型,也不能表示数组类型。在conversion-function-id中的conversion-type-id是最长可能的conversion-declarators序列。[注:这可以防止在声明符*和乘法操作符之间产生歧义。例如:

&ac.operator int*i;        // syntax error:

// parsed as: &(ac.operator int *) i

// not as: &(ac.operator int)*i

这里的*是指针声明符而不是乘法操作符。]

5、转换函数是可继承的。

6、转换函数可为虚函数。

posted @ 2006-04-14 19:16  Goncely  阅读(156)  评论(0编辑  收藏  举报