1.
运算符重载:
重载运算符函数可以对运算符作出新的解释,但原有基本语义不变。是一种特殊的成员函数或友元函数不改变运算符的优先级
不改变运算符的结合性
不改变运算符所需要的操作数
不能创建新的运算符
语法形式为:
类型 类名 :: operator op ( 参数表 )
{
// 相对于该类定义的操作,一个运算符被重载后,原有意义没有失去,只是定义了相对一特定类的一个新运算符
}
#include<iostream>
#include<cstdlib>
using namespace std;
class Calculator
{ public:
Calculator() { value = 0 ; } ;//构造函数初始化
void operator ++ () ;//重载了运算符++
void operator -- () ; //重载了运算符--
unsigned int operator() () ;//重载了运算符()
private:
unsigned int value;
};
int main()
{ Calculator Counter ;
int i ;
for( i = 0 ; i < 5 ; i ++ )
{ ++ Counter;//相当于Counter.operator++()
cout << "\n Counter = " << Counter() ;
}
for( i = 0 ; i <= 5 ; i ++ )
{ -- Counter;//相当于Counter.operator--()
cout << "\n Counter = " << Counter() ;//相当于Counter.operator++()()
}
}
void Calculator::operator ++ ()
{ if ( value < 65535 ) value ++ ;
else
{ cout << "\nData overflow !" << endl ;
exit( 0 ) ;//退出
}
}
void Calculator::operator --()
{ if ( value > 0 ) value -- ;
else
{ cout << "\n Data overflow !" << endl ;
exit( 0 ) ;//退出
}
}
unsigned int Calculator::operator() ()
{ return value ; }
2.
用成员函数或友元函数重载运算符:
运算符函数可以重载为成员函数或友元函数关键区别在于成员函数具有 this 指针,友元函数没有this指针
不管是成员函数还是友元函数重载,运算符的使用方法相同
但传递参数的方式不同,实现代码不同,应用场合也不同
一元运算符:Object op 或 op Object
二元运算符:ObjectL opObjectR
#include<iostream>//三维坐标的简单算术运算
using namespace std;
class TriCoor
{ public:
TriCoor( int mx = 0, int my = 0, int mz = 0 ) { x = mx ; y = my ; z = mz ; }
TriCoor operator + ( TriCoor t )
{ TriCoor temp ;
temp.x = x+t.x ; temp.y = y+t.y ; temp.z = z+t.z ;
return temp ;
}
TriCoor operator = ( TriCoor t ) { x = t.x ; y = t.y ; z = t.z ; return * this ; }
TriCoor operator ++ () { x ++ ; y ++ ; z ++ ; return *this ; }
void show() { cout << x << " , " << y << " , " << z << "\n"; }
void assign( int mx, int my, int mz ) { x = mx; y = my; z = mz; }
private: int x, y, z ; // 3_d coordinates
} ;
int main()
{ TriCoor a( 1, 2, 3 ), b, c ;
a.show(); b.show(); c.show();
for( int i = 0; i < 5; i ++ ) ++ b; b.show() ;
c.assign( 3, 3, 3 ) ; c = a + b + c ; c.show() ;
c = b = a ; c.show() ;
}
3.用友元函数重载:友元函数重载运算符常用于运算符的左右操作数类型不同的情况
在第一个参数需要隐式转换的情形下,使用友元函数重载运算符是正确的选择
例如:
class Complex
{ int Real ; int Imag ;
public :
Complex ( int a ) { Real = a ; Imag = 0 ; }
Complex ( int a , int b ) { Real = a ; Imag = b ; }
friend Complex operator + ( Complex ) ;
}
int main()
{Complex z ( 2 , 3 ) , k ( 3 , 4 ) ;
z= z + 27 ; //正确,相当于z . operator + ( 27 ),调用构造函数将27 转换为 Complex 类常量
z = 27 + z ;//错误,27 不是Complex对象不能调用函数,成员函数重载的“ + ”运算符不支持交换律
}
友元函数没有 this 指针,所需操作数都必须在参数表显式声明
C++中不能用友元函数重载的运算符有:= () [] ->
#include<iostream>//复数运算
usingnamespace std;
classComplex
{public:
Complex( double r =0, double i=0 ) { Real = r ; Image = i; }
Complex(inta) { Real = a ; Image = 0 ; }
void print() const;
friend Complex operator+ ( constComplex & c1, const Complex & c2 ) ;
friend Complex operator- ( constComplex & c1, const Complex & c2 ) ;
friend Complex operator- ( constComplex & c ) ;
private:
double Real, Image ;
};
Complexoperator + ( const Complex & c1, constComplex & c2 )
{ double r = c1.Real + c2.Real ; double i= c1.Image+c2.Image ;
return Complex ( r, i) ;//构造返回对象
}
Complexoperator - ( const Complex & c1, constComplex & c2 )
{ double r = c1.Real - c2.Real ; double i= c1.Image - c2.Image ;
return Complex ( r, i) ;//构造返回对象
}
Complexoperator- ( const Complex & c )
{ return Complex ( -c.Real,- c.Image ) ; }
voidComplex :: 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 ; // operator+(25,c2)
c.print() ;
c = c2 + 25 ; // operator+(c2,52)
c.print() ;
c = - c1 ; // operator-(c1)
c.print() ;
}
使用友元重载运算符的讨论:
若一个运算符的操作需要修改类对象状态时,应该用成员函数重载;需要左值操作数的运算符(如 ++,--),若重载为友元函数时要用引用参数
TriCoor operator ++ ( TriCoor & opl )
{ opl . x ++; opl . y ++; opl . z ++; return opl ; }
TriCoor ob ( 1 , 2 , 3 ) ;
ob ++; // 正确,也可以用指针不用引用参数,这种方式需要接收返回值
4.
重载"++","--":
前置方式: ++Aobject--Aobject
一元 成员函数 重载 A :: A operator++ () ; 解释为:Aobject . operator ++( ) ;
友元函数 重载 friend A operator++ (A &) ; 解释为:operator ++( Aobject ) ;
后置方式: Aobject ++Aobject --
二元 成员函数 重载 A :: A operator++ (int) ; 解释为: Aobject . operator ++( 0 ) ;//伪参数
友元函数 重载: friend A operator++ (A &, int) ; 解释为: operator++(Aobject, 0) //伪参数
#include<iostream>//成员函数重载++
using namespace std;
class increase
{public:
Increase( ) { value=0; }
void display( ) const{ cout<<value<<'\n'; } ;
Increase operator ++ ( ) ; // 前置
Increase operator ++ ( int) ; // 后置
private: unsigned value ;
};
Increase Increase:: operator ++ ( )
{ value ++ ; return *this ; }
Increase Increase:: operator ++ ( int )
{ Increase temp; temp.value= value ++ ; return temp; }
intmain( )
{ Increase a , b , n ; int i;
for ( i= 0 ; i < 10 ; i ++ ) a = n ++ ;
cout<<"n= " ; n.display() ; cout<<"a= " ; a.display() ;
for ( i= 0 ; i < 10 ; i ++ ) b = ++ n ;
cout<< "n= " ; n.display() ; cout<< "b= " ; b.display() ;
}
#include<iostream>//友元函数重载++
using namespace std;
class increase
{public:
Increase ( ) { value=0; }
void display( ) const { cout<<value<<'\n'; } ;
friend Increase operator ++ ( Increase & ) ; // 前置
friend Increase operator ++ ( Increase &, int ) ; // 后置
private: unsigned value ;
};
Increase operator ++ ( Increase & a )
{ a.value ++ ; return a ; }
Increase operator ++ ( Increase & a, int )//通过引用参数操作对象
{ Increase temp(a); a.value ++ ; return temp; }//复制构造局部对象
int main( )
{ Increase a , b , n ; int i ;
for ( i = 0 ; i < 10 ; i ++ ) a = n ++ ;
cout <<"n= " ; n.display( ) ; cout <<"a= " ; a.display( ) ;
for ( i = 0 ; i < 10 ; i ++ ) b = ++ n ;
cout << "n= " ; n.display( ) ; cout << "b= " ; b.display( ) ;
}
5.
重载赋值运算符
赋值运算符重载用于对象数据的复制operator= 必须重载为成员函数
重载函数原型为:类名 & 类名 :: operator= ( 类名 ) ;
#include<iostream>
#include<cstring>
using namespace std;
class Name
{ public :
Name ( char *pN ) ;
Name( const Name & ) ; //复制构造函数
Name& operator=( const Name& ) ; // 重载赋值运算符
~ Name() ;
protected :
char *pName ;
int size ;
} ;
int main()
{ Name Obj1( "ZhangSan" ) ;
Name Obj2 = Obj1 ; // 调用复制构造函数
Name Obj3( "NoName" ) ;
Obj3 = Obj2 = Obj1 ; // 调用重载赋值运算符函数
}
Name::Name ( char *pN )
{ cout <<" Constructing " << pN << endl ;
pName = new char[ strlen( pN ) + 1 ] ;
if( pName != 0 ) strcpy( pName,pN ) ;
size = strlen( pN ) ;
}
Name::Name( const Name & Obj ) //复制构造函数
{ cout << " Copying " << Obj.pName << " into its own block\n";
pName = new char[strlen( Obj.pName ) + 1 ] ;
if ( pName != 0 ) strcpy( pName, Obj.pName ) ;
size = Obj.size;
}Name & Name::operator= ( const Name & Obj ) // 重载赋值运算符
{ delete []pName ;
pName = new char[ strlen( Obj.pName ) + 1 ] ;
if ( pName != 0 ) strcpy( pName , Obj.pName ) ;
size = Obj.size ;
return *this ;
}
Name::~ Name()
{ cout << " Destructing " << pName << endl ;
delete []pName ;
size = 0;
}
6.
重载运算符 [ ] 和 ( ):运算符 [] 和 () 是二元运算符 [ ] 和 ( ) 只能用成员函数重载,不能用友元函数重载
[] 运算符用于访问数据对象的元素,重载格式类型 类 :: operator[] ( 类型 ) ;#include<iostream>
using namespace std;
class vector
{ public :
vector ( int n ) { v = new int [ n ] ; size = n ; }
~ vector ( ) { delete [ ] v ; size = 0 ; }
int & operator [ ] ( int i ) { return v [ i ] ; }//返回元素的引用this-> v[i]
private :
int * v ; int size ;
};
int main ( )
{ vector a ( 5 ) ;
a [ 2 ] = 12 ;//返回引用的函数调用作左值
cout << a [ 2 ] << endl ;
}
()运算符用于函数调用:重载格式 类型 类 :: operator() ( 参数表 ) ;
#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 ;
}
7.
重载流插入和流提取运算符:istream 和 ostream 是 C++ 的预定义流类
cin 是 istream 的对象,cout 是 ostream 的对象
运算符 << 由ostream 重载为插入操作,用于输出基本类型数据
运算符 >> 由 istream 重载为提取操作,用于输入基本类型数据
用友元函数重载 << 和 >> ,输出和输入用户自定义的数据类型
#include<iostream>
#include<cstdlib>
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 ;
};
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 ;//使用重载版本operator >> (cin , A)
cout << "Output the elements of vector A :\n" ;
cout << A ;//使用重载版本operator << (cout , A)
}
vector::vector( int size )
{ if (size <= 0 || size > 100 )
{ cout << "The size of " << size << " is null !\n" ; 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 ;
}
8.
数据类型转换在程序编译时或在程序运行实现
基本类型 ←→ 基本类型
基本类型 ←→ 类类型
类类型 ←→ 类类型
类对象的类型转换可由两种方式说明:构造函数 转换函数
构造函数进行类型转换:
class X
{ // ……
public :
X ( int ) ;
X ( const char * , int = 0 ) ;
};
void f ( X arg ) ;
:
X a = X( 1 ) ; // a = 1,调用构造函数 X ( int ) 把 1 转换为类类型 X 后赋给对象 a,也称 X ( 1 ) 为 X 类的类型常量
X b = "Jessie" ; // b = X ( "Jessie" , 0 ),调用构造函数X ( const char * , int = 0 ) 把字符串转换为类类型 X 后赋给对象 b
a = 2 ; // a = X ( 2 ),隐式调用构造函数 X ( int ) 把 2 转换为类类型 X 后赋给对象
f ( 3 ) ; // f ( X ( 3 ) ),隐式调用构造函数 X ( int ) 对实参作类类型转换,然后做参数结合
f ( 10 , 20 ) ; // error当找不到匹配的构造函数时转换失败
类型转换函数进行类型转换:
带参数的构造函数不能把一个类类型转换成基本类型类类型转换函数是一种特殊的成员函数,提供类对象之间显式类型转换的机制
class X
{ ……
public :
operator int ( ) ;
……
} ;
void f ( X a )
{ int i = int ( a ) ;
i = ( int ) a ;
i = a ;//a 是一个类对象,以上三种它们都用类型转换函数作类型转换,X :: operator int (),对象 a可直接用在整型变量出现的地方
}
类型转换函数有两种使用方式:隐式使用 i = a ;
显式使用 i = a . operator int ( )// int ( a ) ( int ) a
使用不同函数作类型转换函数:
int i = a ; // 用类型转换函数进行转换
X i = a ; // 用构造函数进行转换
9.
#include<iostream>//有理数的计算
using namespace std;
class Rational
{
public:
Rational(); //构造函数
Rational(int n, int d = 1); //构造函数
Rational(double x); //构造函数,double-->Rational
operator double(); //类型转换函数,Rational-->double
friend Rational operator+(const Rational &, const Rational &);
friend ostream & operator<<(ostream &, const Rational &);
private:
int Numerator, Denominator;
};
int gcd(int a, int b); //求最大公约数
int main()
{
Rational a(2, 4);
Rational b = 0.3;
Rational c = a + b;
cout << double(a) << " + " << double(b) << " = " << double(c) << endl;
cout << a << " + " << b << " = " << c << endl;
double x = b;
c = x + 1 + 0.6;
cout << x << " + " << 1 << " + " << 0.6 << " = " << double(c) << endl;
cout << Rational(x) << " + " << Rational(1) << " + " << Rational(0.6) << " = " << c << endl;
return 0;
}
Rational::Rational() //构造等于0的对象
{
Numerator = 0; Denominator = 0;
}
Rational::Rational(int n, int d) //用分子、分母构造对象
{
int g;
if (d == 1) //分母等于1
{
Numerator = n; //分子
Denominator = d; //分母
}
else //分母不等于1的有理数
{
g = gcd(n, d); //求分子、分母的最大公约数
Numerator = n / g; //约分
Denominator = d / g;
};
}
Rational::Rational(double x) //用实数构造对象
{
int a, b, g;
a = int(x*1e5); //分子
b = int(1e5); //分母
g = gcd(a, b); //求分子、分母的最大公约数
Numerator = a / g; //约分
Denominator = b / g;
}
Rational::operator double() //类型转换函数,Rational-->double
{
return double(Numerator) / double(Denominator);
}
//重载运算符 +
Rational operator+(const Rational & r1, const Rational & r2)
{
int n, d;
n = r1.Numerator * r2.Denominator
+ r1.Denominator * r2.Numerator;
d = r1.Denominator * r2.Denominator;
return Rational(n, d);
}
//重载运算符 <<
ostream & operator<<(ostream & output, const Rational & x) {
output << x.Numerator;
if (x.Denominator != 1)
output << "/" << x.Denominator;
return output;
}
int gcd(int a, int b) //求最大公约数
{
int g;
if (b == 0) g = a;
else g = gcd(b, a%b);
return g;
}