第 19讲 几种常见的运算符重载及类型转换
教学目的与要求:
了解几种常见的运算符重载函数 。
掌握类型转换函数的声明和使用 。
教学内容提要:
1,几种常见的运算符重载函数;
2,类型转换;
教学重点:类型转换 。
教学难点:几种常见的运算符重载函数 。
教学进度,P182~P199
教学过程:
19.1 几个常用运算符的重载
19.1.1 单目运算符,++”和,--”的重载在 C++中,可以通过在运算符函数参数表中是否插入关键字 int来区分前缀和后缀这两种方式 。
◆ 对于前缀方式 ++ob,可以用运算符函数重载为
ob.operator ++(); // 成员函数重载或 operator ++ (X& ob); // 友元函数重载,
其中 ob为类 X对象的引用
◆ 对于后缀方式 ob++,可以用运算符函数重载为
ob.operator ++(int); // 成员函数重载或 operator++(X& ob,int); // 友元函数重载在调用后缀方式的函数时,参数 int一般被传递给值 0。
例 19.1,下面是 ++和 --运算符的重载的例子:
#include <iostream.h>
class test {
int t1,t2;
public:
test(int,int);
test operator++(); // 前缀
test operator++(int); // 后缀
test operator--(); // 前缀
test operator--(int); // 后缀
};
test::test(int a,int b){t1=a;t2=b;}
test test::operator++()
{
cout << ″++test\ n″;
++t1; ++t2;
return *this;
}
(续)
test test::operator++(int)
{ cout <<,test++\n”;
int tmp1=t1;
int tmp2=t2;
t1++;t2++;
return test(tmp1,tmp2);
}
test test::operator--()
{ cout <<,—test\n”;
--t1;--t2;
return *this;
}
test test::operator--(int)
{ cout <<,test--\n”;
int tmp1=t1;
int tmp2=t2;
--t1;--t2;
return test(tmp1,tmp2);
}
(续)
void main()
{
test b(3,4);
++b; // t1=4;t2=5
b++; // t1=5;t2=6
--b; // t1=4;t2=5
b--; // t1=3;t2=4
}
在运算符重载中,++和 --后缀运算符被看成一个二元运算符,在其参数类表中有一个参数声明,但是在这个函数被调用时,这个参数值总为 0,函数内部不需要访问这个参数。
19.1.2 赋值运算符,=”的重载对任一类 X,如果没有用户自定义的赋值运算符函数,那么系统自动地为其生成一个缺省的赋值运算符函数,定义为类 X
中的成员到成员的赋值,例如,
X &X::operator=(const X& source)
{
//… 成员间赋值
}
若 obj1和 obj2是类 X的两个对象,obj2已被创建,则编译程序遇到如下语句,
obj1=obj2;
就调用缺省的赋值运算符函数,将对象 obj2的数据成员的值逐个赋给对象 obj1的对应数据成员中。
1.指针悬挂问题在某些特殊情况下,如类中有指针类型时,使用缺省的赋值运算符函数会产生错误。
例 19.2 使用缺省的赋值运算符函数产生错误的例子 。
#include <iostream.h>
#include<string.h>
class string {
public:
string(char *s)
{
ptr=new char[strlen(s)+1];
strcpy(ptr,s);
}
~string()
{ delete []ptr; }
void print()
{ cout<<ptr<<endl; }
private:
char *ptr;
};
void main()
{
string p1("book");
string p2("pen");
p1=p2;
cout<<"p2:";
p2.print();
cout<<"p1:";
p1.print();
}
例 19.3 重载赋值运算符解决指针悬挂问题 。
#include <iostream.h>
#include<string.h>
class string {
public:
string(char *s)
{ ptr=new char[strlen(s)+1]; strcpy(ptr,s);}
~string(){ delete[] ptr; }
void print(){ cout<<ptr<<endl; }
2,重载赋值运算符解决指针悬挂问题为了解决上述使用缺省的赋值运算符所遇到的指针悬挂问题,必须重载赋值运算符,使得对目标对象数据成员指针的赋值,是把原对象指针 ptr所指向的内容传递给它,而不是简单地传递指针值。
string& operator=(const string&);//声明赋值运算符重载函数
private:
char *ptr;
};
string& string::operator=(const string& s)
{ if (this==&s) return *this; // 防止 s=s的赋值
delete [] ptr; // 释放掉原区域
ptr=new char[strlen(s.ptr)+1]; // 分配新区域
strcpy(ptr,s.ptr); // 字符串拷贝
return *this;
}
void main()
{ string p1("book");
string p2("pen");
p1=p2;
cout<<"p2:"; p2.print();
cout<<"p1:"; p1.print();
}
[]运算符 一般是用在数组中来标识数组元素的位置,是可以出现在等号左边作为左值的。其中对于数组数据的赋值和取值就是通过[]运算符的重载来实现的。
成员函数的声明:
返回值类型 类名,:operator [](形参 )
注意,形参在此表示下标例 19.4
#include <iostream.h>
class Vector4
{ public:
Vector4(int a1,int a2,int a3,int a4)
{ v[0]=a1; v[1]=a2; v[2]=a3; v[3]=a4;}
private:
int v[4];
};
19.1.3 []的重载
void main()
{ Vector4 v(1,2,3,4);
cout <<v[2];//error
v[3]=v[2];//error
}
要使得上述程序合法,只需在 Vector4中增加 []运算符重载函数以下是完整的程序,
#include <iostream.h>
class Vector4
{ public:
Vector4(int a1,int a2,int a3,int a4)
{ v[0]=a1; v[1]=a2; v[2]=a3; v[3]=a4;}
int &operator[](int);
private:
int v[4];
};
int&Vector::operator[](int bi)
{
if(bi<0||bi>=4)
{ cout<<“Bad subscript\n”
exit(1);
}
return v[bi];
}
void main()
{ Vector4 v(1,2,3,4);
cout <<v[2]; v[3]=v[2];
cout<<v[3];
}
19.2 类型转换与转换函数
19.2.1由其他类型转换为类类型,
class complex
{ double real,imag;
public:
complex(double r=0,double i =0)
{real=r;imag=i;}
void print()
{ cout<<“(”<<real<<“,”<<imag<<“)”<<endl;}
};
void main()
{ complex c1(2.3,4.5);
c1.print();
c1=12; c1.print();
c1=complex(5); c1.print();
}
19.2.2由类类型转换为其他类型 ( 类型 转换重载函数 )
1,格式,operator<数据类型 >( )
{函数体 }
2,举例:
class complex
{ …
operator double();
{ return double(real); }

};
void main( )
{ complex c1(2.3,4.5);
c1.print();
cout<<c1*3.333<<endl; //隐含的类型转换
}
小结:
1,++和 --运算符重载 。
2,=运算符重载 ( 指针悬挂 )
3,类型转换 (类型转换重载函数 )
作业:
P210 5.15,5.13,5.14