复习四——运算符重载

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;
}

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

季沐晴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值