1、格式
类型 类名::operator op(参数表)
{
}
例一,设计一个安全计数器,重载自增、自减、括号运算符
#include<iostream>
#include<cstdlib>//后面有abort();
using namespace std;
class calculator
{
public:
calculator(){value=0;}
void operator++();//重载自增运算符
void operator--();//重载自减
unsigned int operator()()const;//重载括号,unsigned int ,无符号整型
private:
unsigned int value;
};
void calculator::operator++()
{
if(value<65535)
++value;
else
{
cout<<"!"<<endl;
abort();//退出程序
}
}
void calculator::operator--()
{
if(value>0)
--value;
else
{
cout<<"!"<<endl;
abort();//退出程序
}
}
unsigned int calculator::operator()()const
{
return value;
}
int main()
{
calculator counter;
int i;
for(i=0;i<5;i++)
{
++counter;//counter.operator++()
cout<<"!"<<counter()<<endl;
}
for(i=0;i<5;i++)
{
--counter;//counter.operator--()
cout<<"!"<<counter()<<endl;
}
}
2.用成员或友元函数重载运算符
(1)一元运算符 object op 或 op object
重载为成员函数,解释为:Object . operator op (),操作数由对象Object通过this指针隐含传递
重载为友元函数,解释为:operator op (Object),操作数由参数表的参数Object提供
(2)二元运算符 objectL op objectR
重载为成员函数,解释为:ObjectL . operator op ( ObjectR )
左操作数由ObjectL通过this指针传递,右操作数由参数ObjectR传递
重载为友元函数,解释为:operator op ( ObjectL, ObjectR )
左右操作数都由参数传递
A。当一元运算符的操作数,或者二元运算符的左操作数是类的对象时,定义重载算符函数为成员函数
例二,建立一个描述3维坐标的类 Tri_Coor,重载运算符 “+”、“++”、和 “=” ,实现简单的算术运算
#include<iostream>
using namespace std;
class TriCoor
{
public:
TriCoor(int mx=0,int my=0,int mz=0);
TriCoor operator+(TriCoor t);//对加法的重载
TriCoor operator++();
TriCoor operator=(TriCoor t);
void show();
void assign(int mx,int my,int mz);
private:
int x,y,z;//三维坐标
};
TriCoor::TriCoor(int mx,int my,int mz)
{
x=mx;
y=my;
z=mz;
}
TriCoor TriCoor::operator+(TriCoor t)
{
TriCoor temp;
temp.x=x+t.x;
temp.y=y+t.y;
temp.z=z+t.z;
return temp;//调用复制构造,析构
}
TriCoor TriCoor::operator++()
{
x++;
y++;
z++;
return *this;
}
TriCoor TriCoor::operator=(TriCoor t)
{
x=t.x;
y=t.y;
z=t.z;
return *this;
}
void TriCoor::show()
{
cout<<x<<","<<y<<","<<z<<"\n";
}
void TriCoor::assign(int mx,int my,int mz)
{
x=mx;
y=my;
z=mz;
}
int main()
{
TriCoor a(1,2,3),b,c;
a.show();
b.show();
c.show();
for(int i=0;i<5;i++)
{
++b;//自增在前,代表他所调用的成员函数无参
//b.operator ++ ()
}
b.show();
c.assign(3,3,3);
c=a+b+c;
c.show();
c=b=a;//b.operator = (a), c.operator = (b)
c.show();
}
B。友元函数重载运算符常用于运算符的左右操作数类型不同的情况
例三:
class Complex
{ int Real ; int Imag ;
public :
Complex ( int a ) { Real = a ; Imag = 0 ; }
Complex ( int a , int b ) { Real = a ; Imag = b ; }
Complex operator + ( Complex ) ;
…...
} ;
int f ( )
{ Complex z ( 2 , 3 ) , k ( 3 , 4 ) ;
z = z + 27 ; //z . operator + ( 27 )
z = 27 + z ; //错的因为等价于 27 . operator + ( z ) 但是27不是Complex对象不能调用函数
…...
}
a.在第一个参数需要隐式转换的情形下,使用友元函数重载运算符是正确的选择
b.友元函数没有 this 指针,所需操作数都必须在参数表显式声明,很容易实现类型的隐式转换
c.C++中不能用友元函数重载的运算符有
= () []
如果用友元函数重载运算符,左右操作数都由参数传递,则表达式z=27+z;被解释为operator+(27,z);
例四,复数运算
#include<iostream>
using namespace std;
class Complex
{
public:
Complex(double r=0,double i=0);
Complex(int a)
{
real=a;
image=0;
}
void print()const;
friend Complex operator+(const Complex&c1,const Complex&c2);
friend Complex operator-(const Complex&c1,const Complex&c2);
friend Complex operator-(const Complex&c);//重载负号
private:
double real,image;//实部虚部
};
Complex::Complex(double r,double i)
{
real=r;
image=i;
}
Complex operator+(const Complex&c1,const Complex&c2)
{
double r=c1.real+c2.real;
double i=c1.image+c2.image;
return Complex(r,i);
}
Complex operator-(const Complex&c1,const Complex&c2)
{
double r=c1.real-c2.real;
double i=c1.image-c2.image;
return Complex(r,i);
}
Complex operator-(const Complex&c)
{
return Complex(-c.real,-c.image);
}
void Complex::print()const
{
cout<<'('<<real<<","<<image<<')'<<endl;
}
int main()
{
Complex c1(2.5,3.7),c2(4.2,6.5);
Complex c;
c=c1-c2;//operator-(c1,c2)
c.print();
c=25+c2;
c.print();
c=c2+25;
c.print();
c=-c1;
c.print();
}
3.重载++和--;
设 A Aobject ;
运算符 ++和 - - 有两种方式:
(1)前置方式(无参): ++Aobject --Aobject
一元 成员函数 重载 A :: A operator++ () ;
解释为: Aobject . operator ++( ) ;
友元函数 重载 friend A operator++ (A &) ;
解释为: operator ++( Aobject ) ;
(2)后置方式(有参): Aobject ++ Aobject --
二元 成员函数 重载 A :: A operator++ (int) ;
解释为: Aobject . operator ++( 0 ) ;
友元函数 重载: friend A operator++ (A &, int) ;
解释为: operator++(Aobject, 0)
4.重载赋值运算符
(1)赋值运算符重载用于对象数据的复制
(2)operator= 必须重载为成员函数
(3)重载函数原型为:
类名 & 类名 :: operator= ( 类名 ) ;
5.重载运算符[]和()
(1)运算符 [] 和 () 是二元运算符
(2)[] 和 () 只能用成员函数重载,不能用友元函数重载
(3)重载格式 类型 类 :: operator[] ( 类型 ) ;
设 x 是类 X 的一个对象,则表达式
x [ y ]
可被解释为
x . operator [ ] ( y )
(4)重载格式 类型 类 :: operator() ( 参数表 ) ;
设 x 是类 X 的一个对象,则表达式
x ( arg1, arg2, … )
可被解释为
x . operator () (arg1, arg2, … )
//例五,重载下标运算符 []
#include<iostream>
using namespace std;
class vector
{
public:
vector(int n)
{
v=new int[n];//new 动态数组,开辟动态空间
size=n;
}
~vector(){delete[]v;size=0;}
int &operator[](int i)//返回元素的引用
{
return v[i];
}
private:
int*v;int size;
};
int main()
{
vector a(5);
a[2]=12;
cout<<a[2]<<endl;
}
//例六,用重载()运算符实现数学函数的抽象
#include<iostream>
using namespace std;
class F
{
public:
double operator()(double x,double y);
};
double F::operator()(double x,double y)
{
return x*x+y*y;
}
int main()
{
F f;
cout<<f(5.2,2.5)<<endl;
}
5.重载流插入和流提取运算符
(1)istream 和 ostream 是 C++ 的预定义流类
(2)cin 是 istream 的对象,cout 是 ostream 的对象
(3)运算符 << 由ostream 重载为插入操作,用于输出基本类型数据
(4)运算符 >> 由 istream 重载为提取操作,用于输入基本类型数据
(5)用友元函数重载 << 和 >> ,输出和输入用户自定义的数据类型
例七,vector类重载流插入运算符和提取运算符象
#include<iostream>
#include<cstdlib>//exit(0);
using namespace std;
class vector
{
public:
vector(int size=1);
~vector();
int&operator[](int i);
friend ostream&operator<<(ostream&output,vector&);
friend istream&operator>>(istream&input,vector&);
private:
int*v;
int len;
};
vector::vector(int size)
{
if(size<=0||size>100)
{cout<<"The size of"<<size<<"is";
exit(0);}
v=new int[size];
len=size;
}
vector::~vector()
{
delete[]v;
len=0;
}
int&vector::operator[](int i)
{
if(i>=0&&i<len)
return v[i];
cout<<"The subscript"<<i<<"is outside!\n";
exit(0);
}
ostream&operator<<(ostream&output,vector&ary)
{
for(int i=0;i<ary.len;i++)
output<<ary[i]<<" ";
output<<endl;
return output;
}
istream&operator>>(istream&input,vector&ary)
{
for(int i=0;i<ary.len;i++)
input>>ary[i];
return input;
}
int main()
{
int k;
cout<<"Input the length of vector A :\n" ;
cin>>k;
vector A(k);
cout << "Input the elements of vector A :\n" ;
cin>>A;
cout << "Output the elements of vector A :\n" ;
cout<<A;
}
6.类型转换函数
(1)
数据类型转换在程序编译时或在程序运行实现
基本类型 ←→ 基本类型
基本类型 ←→ 类类型
类类型 ←→ 类类型
类对象的类型转换可由两种方式说明:
构造函数 转换函数
称为用户定义的类型转换或类类型转换,有隐式调用和显式调用方式
(2)
类型转换函数有两种使用方式:
隐式使用 i = a ;
显式使用 i = a . operator int ( ) // int ( a ) ( int ) a
(3)
使用不同函数作类型转换函数:
int i = a ; // 用类型转换函数进行转换
X i = a ; // 用构造函数进行转换
(4)
语法形式:
X :: operator T ( )
{ ……
return T 类型的对象
}
功能:将类型 X 的对象转换为类型 T 的对象
T 可以是预定义类型,也可以是用户定义类型
函数没有参数,没有返回类型,但必须有一条 return 语句,返回
T 类型的对象
该函数只能为成员函数,不能为友元
//例八,简单串类和字符串之间的类型转换
#include<iostream>
#include<cstring>
using namespace std;
class String
{
char*data;
int size;
public:
String(char*s)
{
size=strlen(s);
data=new char(size+1);
strcpy(data,s);
}
operator char*()const//类型转化函数
{
return data;
}
};
int main()
{
String sobj="hell";
char*svar=sobj;//把String类型对象赋给了字符串常量,进行了类型转换
cout<<svar<<endl;
}
补充:动态数组
在上学期数组中学了new和delete,提到了动态数组
用new运算符申请基本类型空间时,可以用()对存储区赋初值
#include<iostream>
using namespace std;
int main()
{
int *p=NULL;
p=new int(89);//初始化存储区
if(p==NULL)
{
cout<<"\0";
return o;
}
cout<<*p<<endl;
delete p;
p=NULL;
return 1;
}
编写函数,申请动态数组
#include<iostream>
using namespace std;
void App(int* & pa,int n);
int main()
{
int *ary=NULL,*t;
int i,n;
cout<<"n=";
cin>>n;
App(ary,n);//调用函数,动态分配数组
for(t=ary;t<ary+n;t++)
cout<<*t<<" ";
cout<<endl;
for(i=0;i<n;i++)
ary[i]=10+i;//对动态数组元素赋值
for(i=0;i<n;i++)
cout<<ary[i]<<" ";
cout<<endl;
delete[]ary;
ary=NULL;
}
void App(int* &pa,int len)//pa是指针引用类型
{
pa=new int[len];//动态分配数组
if(pa==NULL)
{
cout<<"!\n";
return;
}
for(int i=0;i<len;i++)//赋初值
pa[i]=0;
}