运算符重载
*多态性的概念
面向对象理论中有3个术语:对象、方法和消息:
对象(object):是构成系统的基本单位,
两个要素:属性和行为,
在C++中,对象由数据和函数两部分组成:数据即是对象的属性, 行为也称为方法(method),是对数据的操作,通常由函 数实现。
调用对象中的函数就是向该对象传送一个消息(message),所谓“消息”,其实就是一个命令。例如:stud.display();就是向对象stud发出的一个“消息”,通知它执行其中的display“方法”(即display函数)。即:
stud是对象, display()是方法, 语句“stud.display();”是消息。
多态性是面向对象程序设计的重要特征之一。
多态性:发出同样的消息被不同类型的对象接收时有可能导致完全不同的行为。
多态的实现:
编译时的多态:在编译的过程中确定同名操作的具体对象,通过: 函数重载,运算符重载来完成。
运行时的多态:程序运行前无法根据函数名和参数来确定该调 用哪个函数,必须在程 序执行的过程中,根据具体的情况来动 态的确定。通过 类继承,虚函数来完成。
*运算符重载
1.运算符重载:对已有的运算符赋予多重含义,实质是函数重载,提供了C++的可扩展性。
2.实现机制
(1).转化:运算表达式转化为对运算符函数的调用,运算对象转化为运算符函数的实参。
(2).编译系统对冲在运算符的选择,遵循函数重载的选择原则:目前可以简单的理解为通过函数的参数表判断调用的是重载中的哪个参数
3.重载运算符的限制
(1).不能重载的运算符
成员访问运算符. ‘.’在类中对任何成员都有意义,已经成为标准用法。
作用域运算符::
成员指针访问运算符.“”为了处理特殊情况而设计,在一般程序设计中通常不需要用到
条件运算符?: 这个运算符对于类对象来说没有实际意义,相反还会引起歧义
Sizeof 不要当作普通的运算符
(2).可以重载的运算符
算术运算符:+,-,,/,%,++,–;
位操作运算符:&,|,~,^(位异或),<<(左移),>>(右移);
逻辑运算符:!,&&,||;
比较运算符:<,>,>=,<=,==,!=;
赋值运算符:=,+=,-=,=,/=,%=,&=,|=,^=,<<=,>>=;
其他运算符:[],(),->,(逗号运算符),new,delete,new[],delete[],
->
*用成员或友元函数重载运算符
运算符重载的两种形式
运算符重载为类的成员函数
运算符重载为类的友元函数
关键区别在于: 成员函数具有 this 指针,友元函数没有this指针
不管是成员函数还是友元函数重载,运算符的使用方法相同。
传递参数的方式不同,实现代码不同,应用场合也不同 。
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) 左右操作数都由参数传递。
重载为类的成员函数时
参数个数=原操作数个数-1 (后置++、–除外)
重载为友元函数时
参数个数=原操作数个数,且至少应该有一个自 定义类型形参。
一、用成员函数重载运算符
例:将“+”,“-”运算重载为复数类的成员函数
#include<iostream>
using namespace std;
class Complex //复数类声明
{
public: //外部接口
Complex(double r=0.0,double i=0.0)
{ real=r; imag=i; } //构造函数
Complex operator + (Complex c2); //+重载为成员函数
Complex operator - (Complex c2); //-重载为成员函数
void display(); //输出复数
private: //私有数据成员
double real; //复数实部
double imag; //复数虚部
};
Complex Complex::operator + (Complex c2) //重载函数实现
{
Complex c;
c.real=real+c2.real;
c.imag=imag+c2.imag;
return Complex(c.real,c.imag);
}
Complex Complex::operator - (Complex c2) //重载函数实现
{
Complex c;
c.real=real-c2.real;
c.imag=imag-c2.imag;
return Complex(c.real,c.imag);
}
void Complex::display()
{ cout<<"("<<real<<","<<imag<<")"<<endl; }
int main() //主函数
{ Complex c1(5,4),c2(2,10),c3; //声明复数类的对象
cout<<"c1="; c1.display();
cout<<"c2="; c2.display();
c3=c1-c2; //使用重载运算符完成复数减法
cout<<"c3=c1-c2=";
c3.display();
c3=c1+c2; //使用重载运算符完成复数加法
cout<<"c3=c1+c2=";
c3.display();
}
//程序输出的结果为:
c1=(5,4) c2=(2,10) c3=c1-c2=(3,-6) c3=c1+c2=(7,14)
二、用友元函数重载运算符
友元函数重载运算符常用于运算符的左右操作数
C++中不能用友元函数重载的运算符有
= () [] ->
例 复数运算
#include<iostream>
using namespace std;
class Complex
{ public:
Complex(double r=0,doublei=0 ) {Real = r;Imag = i;}
Complex(int a) { Real = a ; Imag = 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, Imag ;
};
Complex operator + ( const Complex & c1, const Complex & c2 )
{ double r = c1.Real + c2.Real ;
double i = c1.Imag+c2.Imag ;
return Complex ( r, i ) ;
}
Complex operator - ( const Complex & c1, const Complex & c2 )
{ double r = c1.Real - c2.Real ;
double i = c1.Imag - c2.Imag ;
return Complex ( r, i ) ;
}
Complex operator- ( const Complex & c )
{ return Complex ( -c.Real, - c.Imag ) ; }
void Complex :: print() const
{ cout << '(' << Real << " , "<< Imag << ')'<< 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() ;
}
## 成员函数重载++
#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; }
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( ) ;
}
//运行结果
n=10
a=9
n=20
b=20
## 友元函数重载++
#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( ) ;
}
*重载赋值运算符
赋值运算符重载用于对象数据的复制,只能用成员函数重载,重载函数原型:类名 & 类名 ::operator=(const 类名&);
例 定义Name类的重载赋值函数
#include<iostream>
#include<cstring>
using namespace std;
class Name
{ public :
Name ( char *pN ) ;
Name( const Name & Obj ) ; //复制构造函数
Name& operator=( const Name &Obj ) ; // 重载赋值运算符
~ Name() ;
protected :
char *pName ;
int size ;
} ;
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 lock\n";
pName = new char[strlen( Obj.pName ) + 1 ] ;
if ( pName != 0 ) strcpy( pName, Obj.pName ) ;
size = Obj.size;
}
Name & Name::operator= ( const Name & Obj ) // 重载赋值运算符
{ cout << " reload "<<this->pName<<"="<<Obj.pName<<endl;
if(this == &Obj) return *this;
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;
}
int main()
{ Name Obj1( "ZhangSan" ) ;
Name Obj2 = Obj1 ; // 调用复制构造函数
Name Obj3( "NoName" ) ;
Obj3 = Obj2 = Obj1 ; // 调用重载赋值运算符函数
}
//运行结果
Constructing ZhangSan
Constructing Lisi
Constructing NoName
Constructing helloName
reload Lisi=ZhangSan
reload NoName=ZhangSan
reload helloName=ZhangSan
Destructing ZhangSan
Destructing ZhangSan
Destructing ZhangSan
Destructing ZhangSan
*重载下标运算符[]
[]运算符用于访问数据对象的元素
重载格式: 类型 类 ::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 )
{ if (i>=0&&i<size)
return 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 ;
}
*重载流插入和流提取运算符
istream 和 ostream 是 C++ 的预定义流类
cin 是 istream 的对象,cout 是 ostream 的对象
运算符 << 由ostream 重载为插入操作,用于输出基本类型数据
运算符 >> 由 istream 重载为提取操作,用于输入基本类型数据
用友元函数重载 << 和 >> ,输出和输入用户自定义的数据类型
只能被重载为友元函数
例 为vector类重载流插入运算符和流提取运算符
#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 ;
};
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 ;
}
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 ;
}
运算符重载ppt。72页