• 沒有找到結果。

double fun::operator()(double x,double y,double z) const {

return (x*x+y*y)*z;

}

void main() {

fun f;

cout<<f(3.0,2.0,5.0)<<endl;

}

程序运行结果为:

65

执行 f(3.0,2.0,5.0)时,对象 f 是函数调用运算符“()”的左操作数,而 3.0、2.0、5.0 构成 实参表;其左操作数是 fun 类的对象 f,它将执行对 fun 类的重载函数的调用。

6.4 类型转换

我们在使用重载的运算符时,往往需要在自定义的数据类型和系统预定义的数据类型之 间进行转换,或者需要在不同的自定义数据类型之间进行转换。本节介绍 C++中数据类型的 转换。

6.4.1 系统预定义类型间的转换

对于系统预定义的数据类型,C++提供了两种类型转换方式,即隐式类型转换(或称标准 类型转换)和显式类型转换。

(1)隐式类型转换

隐式类型转换主要遵循以下规则:

 字符或 short 类型变量与 int 类型变量进行运算时,将字符或 short 类型转换成 int 类型;

 float型数据在运算时一律转换为双精度(double)型,以提高运算精度(同属于实型);

 在赋值表达式 A=B 中,赋值运算符右端 B 的值需转换为 A 类型后再进行赋值;

 当两个操作对象类型不一致时,在算术运算前,级别低的自动转换为级别高的类型。

(2)显式类型转换

 强制转换法 (类型名)表达式 例如:

int i,j;

cout<<(float)(i+j);

 函数法

类型名(表达式)

例如:

int i,j;

cout<<float (i+j)

例 6.17 系统预定义类型间转换。

#include<iostream.h>

void main() {

int a=5,sum;

double b=5.55;

sum=a+b;//---①

cout<<"隐式转换:a+b="<<sum<<endl;

sum=(int)(a+b);//---② sum=int(a+b); //---③

cout<<"显式转换:a+b="<<sum<<endl;

}

程序运行结果为:

隐式转换:a+b=10 显式转换:a+b=10

上述代码中的①就是含有隐式类型转换的表达式,在进行“a+b”时,编译系统先将 a 的 值 5 转换为双精度 double,然后和 b 相加得到 10.55,在向整型变量 sum 赋值时,将 10.55 转 换为整型数 10,赋值给变量 sum。这种转换由 C++编译系统自动完成,不需要用户干预。而 上例中的②和③中则涉及到了显式类型转换,它们都是把 a+b 所得结果的值强制转换为整型 数。只是②式是 C 语言中用到的形式“(类型名)表达式”,而③式是 C++中采用的形式“类型 名(表达式)”。

6.4.2 类类型与系统预定义类型间的转换

对于用户自己定义的类类型而言,编译系统并不知道怎样进行转换。解决这个问题的关键 是让编译系统知道怎样去进行这些转换,需要定义专门的函数来处理。C++中提供了如下两种 方法:

 通过转换构造函数进行类型转换;

 通过类型转换函数进行类型转换。

1.通过转换构造函数进行类型转换

转换构造函数(conversion constructor function)的作用是将一个其他类型的数据转换成一 个类的对象。主要有以下几种构造函数:

(1)默认构造函数。以 Complex 类为例,函数原型的形式为:

Complex( ); //没有参数

(2)用于初始化的构造函数。函数原型的形式为:

Complex(double r,double i); //形参列表中一般有两个以上参数

(3)用于复制对象的拷贝构造函数。函数原型的形式为:

Complex (Complex &c); //形参是本类对象的引用

(4)再介绍一种新的构造函数——转换构造函数,转换构造函数只有一个形参,如:

Complex(double r) {real=r;imag=0;}

其作用是将 double 型的参数 r 转换成 Complex 类的对象,将 r 作为复数的实部,虚部为 0。

用户可以根据需要定义转换构造函数,在函数体中告诉编译系统怎样去进行转换。

毫无疑问转换构造函数就是构造函数的一种,只不过它具有类型转换的作用。回顾下例 6.1中两个复数(sum=com1+com2)相加的实例,现在如果想要实现 sum=com1+5.5 该怎么办,

也许首先会想到再定义一个关于复数加双精度数的运算符重载函数,这样做的确可以。另外还 可以定义一个转换构造函数来解决上述问题。可对 Comlex 类(复数类)进行如下改造。

例 6.18 使用转换构造函数完成双精度数到复数的转换。

#include<iostream.h>

class Complex //复数类 {

private://私有

double real;//实数 double imag;//虚数 public:

Complex(double real,double imag) {

this->real=real;

this->imag=imag;

}

Complex(double d=0.0)//转换构造函数 {

real=d;//实数取 double 类型的值 imag=0;//虚数取 0

}

Complex operator+(Complex com1);

void showComplex();

};

Complex Complex::operator+(Complex com1) {

return Complex(real+com1.real,imag+com1.imag);

}

void Complex::showComplex() {

cout<<real;

if(imag>0) cout<<"+";

if(imag!=0)

cout<<imag<<"i"<<endl;

else

cout<<endl;

} int main() {

Complex com(10,10),sum;

sum=com+Complex(5.5);//①

sum.showComplex();//输出运算结果 sum=com+6.6; //②

sum.showComplex();//输出运算结果 sum=5.5; //③

sum.showComplex();//输出运算结果 return 0;

}

程序运行结果为:

15.5+10i 16.6+10i 5.5

main()函数中的语句①显式地调用转换构造函数 Complex(5.5),将 double 类型的 5.5 转换 为无名的 Complex 类的临时对象(5.5+0i),然后执行两个 Complex 类(复数类)对象相加的 运算符重载函数。语句②隐式地调用转换构造函数 Complex(6.6),将 double 类型的 6.6 转换为 无名的 Complex 类的临时对象(6.6+0i),然后执行两个 Complex 类(复数类)对象相加的运 算符重载函数。语句③隐式调用 Complex(5.5),将 double 类型的 5.5 转换为无名的 Complex 类的临时对象(5.5+0i),然后调用缺省的赋值运算符函数完成对 sum 的赋值。所以说一般的 转换构造函数的定义形式如下:

类名(待转换类型) {

函数体;

} 说明:

(1)转换构造函数只有一个形参。

(2)在类体中,可以有转换构造函数,也可以没有转换构造函数,视需要而定。

(3)当几种构造函数同时出现在同一个类中,它们是构造函数的重载。编译系统会根据 建立对象时给出的实参的个数与类型来选择与之匹配的构造函数。

(4)转换构造函数不仅可以将系统预定义类型的数据转换成类对象,也可以将另一个类 的对象转换成转换构造函数所在类的对象。

例如,将一个学生类对象转换为教师类对象,可以在 Teacher 类中定义出下面的转换 构造函数:

Teacher(Student &s) {

num=s.num;

strcpy(name,s.name);

sex=s.sex;

}

但应注意,对象 s 中 num、name 和 sex 必须是公有成员,否则不能在类外被访问。

2.通过类型转换函数进行类型转换

转换构造函数可以把系统预定义类型转化为自定义类的对象,但是却不能把类的对象转 换为基本数据类型。比如,不能将 Complex 类(复数类)的对象转换成 double 类型数据。在 C++中可用类型转换函数(type conversion function)来解决这个问题。类型转换函数的作用是

将一个类的对象转换成另一类型的数据,定义类型转换函数的一般形式为:

class 源类类名{

//…

operator 目标类型( ) {

//…

return 目标类型的数据;

} //…

};

说明:

(1)源类类名为要转换的源类类型,目标类型为要转换成的类型,它既可以是自定义的 类型也可以是系统预定义类型。

(2)类型转换函数的函数名前不能指定返回类型,且没有参数。从函数的形式看,它与 运算符重载函数相似,都是用 operator 开头,只是被重载的是类型名。

(3)类型转换函数只能定义为一个类的成员函数,因为转换的主体是本类对象。不能为 友元函数或普通函数。

(4)类型转换函数中必须有“return 目标类型的数据;”的语句,即必须回传目标类型数 据作为函数的返回值。

(5)在类中可以有多个类型转换函数,C++编译器将根据操作数的类型自动地选择一个 合适的类型转换函数与之匹配。

例 6.19 类型转换函数显式调用举例。

#include<iostream.h>

class Complex{

public:

Complex(float r=0,float i=0) {

real=r;

imag=i;

cout<<"Complex class Constructing...\n";

}

operator float() {

cout<<"Complex changed to float...\n";

return real;

}

operator int() {

cout<<"Complex changed to int...\n";

return int(real);

}

void print()

{ cout<<'('<<real<<','<<imag<<')'<<endl;}

private:

float real,imag;

};

int main() {

Complex a(1.1,3.3);

a.print();

cout<<float(a)*0.5<<endl;

Complex b(2.5,5.5);

b.print();

cout<<int(b)*2<<endl;

return 0;

}

程序运行结果为:

Complex class Constructing...

(1.1,3.3)

Complex changed to float...

0.55

Complex class Constructing...

(2.5,5.5)

Complex changed to int...

4

上例中两次调用了类型转换函数。第一次采用显式调用,将类对象 a 转换成 float 类型。

第二次也是显式调用,将类对象 b 转换为 int 类型。类型转换函数的调用分为显式转换与隐式 转换两种形式,下面通过例 6.20 来说明如何进行隐式转换。

例 6.20 类型转换函数隐式调用的举例。

#include<iostream.h>

class Complex{

public:

Complex(int r,int i) {

real=r;

imag=i;

cout<<"Complex class Constructing...\n";

}

Complex(int i=0) //转换构造函数 { real=imag=i/2;}

operator int() //类型转换函数 {

cout<<"Complex changed to int...\n";

return real+imag;

} void print()

{ cout<<"real:"<<real<<"\t"<<"imag:"<<imag<<endl;}

private:

int real,imag;

};

int main() {

Complex c1(1,2),c2(3,4);

c1.print();

c2.print();

Complex c3;

c3=c1+c2;

c3.print();

}

程序运行结果为:

Complex class Constructing...

Complex class Constructing...

real:1 imag:2 real:3 imag:4

Complex changed to int...

Complex changed to int...

real:5 imag:5

上例中没有在类中重载运算符“+”,为何 c3=c1+c2 成立呢?原因在于 C++自动进行了隐 式转换,将 c1 与 c2 分别都转换成 int 型,然后调用转换构造函数将整型数据转换为 complex 类。这里类型转换函数和转换构造函数构成了互逆操作,转换构造函数 Complex(int)将一个整 型转换成一个 Complex 类型,而类型转换函数 Complex::operator int()将 Complex 类型转换成 整型。

相關文件