运算符重载

一、运算符重载的概念

重载运算符的概念

C++中的表达式由运算符和操作数按照规则构成。

运算符重载就是给已有的运算符赋予多重含义,使同一个运算符作用于不同类型的数据时产生不同的行为。

运算符重载的目的时使得C++中的运算符也能够用来操作对象。

表4-1 可重载的运算符

可重载的运算符 说明
双目算数运算符 +(加),-(减),*(乘),/(除).%(取模)
关系运算符 ==(等于),!=(不等于),<(小于),>(大于),<=(小于等于),>=(大于等于)
逻辑运算符 ||(逻辑或),&&(逻辑与),!(逻辑非)
单目运算符 +(正),-(负),*(指针),&(取地址)
自增自减运算符 ++(自增),--(自减)
位运算符 |(按位或),&(按位与),~(按位取反),^(按位异或),<<(左移),>>(右移)
赋值运算符 =(赋值),+=(加法赋值),-=(减法赋值),*=(乘法赋值),/=(除法赋值),%=(取模赋值),&=(按位与赋值),|=(按位或赋值),^=(按位异或赋值),<<=(左移赋值),>>=(右移赋值)
空间申请与释放 new(创建对象),delete(释放对象),new,delete[(释放数组)
其他运算符 0(函数调用),->(成员访问,,(逗号),

表4-2 不可重载的运算符和符号

可重载的运算符 说明
成员访问运算符 .
成员指针访问运算符 .,->
域运算符 ::
长度运算符 sizeof
条件运算符 ?:
预处理符号 #

有两个运算符,系统提供了默认的重载版本。它们是赋值运算符=和地址运算符&。

对于=,系统默认重载为对象成员变量的复制。对于&,系统默认重载为返回任何类对象的地址。

运算符重载的实质是编写以运算符为名称的函数,使用运算符的表达式就被解释为对重载函数的调用。

函数名由关键字operator和其后要重载的运算符符号构成。

运算符函数的格式

返回值类型 operator 运算符(形参表)
{
  函数体
}

运算符可以被重载为全局函数,也可以被重载为类的成员函数。

重载运算符为类的成员函数

程序4-1 为类myComplex重载运算符“+”和“-”。

#include <iostream>
using namespace std;

class myComplex     //复数类 
{
    private:
        double real,imag;
    public:
        myComplex();
        myComplex(double r,double i);
        void outCom();
        myComplex operator-(const myComplex &c);
        friend myComplex operator+(const myComplex &c1,const myComplex &c2);
};

myComplex::myComplex()
{
    real = 0;
    imag = 0;
}

myComplex::myComplex(double r,double i)
{
    real = r;
    imag = i;
}

void myComplex::outCom()
{
    cout<<"("<<real<<","<<imag<<")";
}

myComplex myComplex::operator-(const myComplex &c)
{
    return myComplex(this->real-c.real,this->imag-c.imag);
}

myComplex operator+(const myComplex &c1,const myComplex &c2)
{
    return myComplex(c1.real + c2.real,c1.imag + c2.imag);
}

int main()
{
    myComplex c1(1,2),c2(3,4),res;
    c1.outCom();
    cout<<"operator+";
    c2.outCom();
    cout<<"=";
    res = c1 + c2;
    res.outCom();
    cout<<endl;
    c1.outCom();
    cout<<"operator-";
    c2.outCom();
    cout<<"=";
    res = c1 - c2;
    res.outCom();
    cout<<endl;
    return 0;
}

(1,2)operator+(3,4)=(4,6)
(1,2)operator-(3,4)=(-2,-2)

重载运算符为友元函数

例4-1中定义的operator-(double r)实现的是复数的实部减去r并返回结果对象。

#include <iostream>
using namespace std;

class myComplex     //复数类 
{
    private:
        double real,imag;
    public:
        myComplex();
        myComplex(double r,double i);
        void outCom();
        myComplex operator-(const myComplex &c);
        myComplex operator-(double r);
};

myComplex::myComplex()
{
    real = 0;
    imag = 0;
}

myComplex::myComplex(double r,double i)
{
    real = r;
    imag = i;
}

void myComplex::outCom()
{
    cout<<"("<<real<<","<<imag<<")";
}

myComplex myComplex::operator-(const myComplex &c)
{
    return myComplex(this->real-c.real,this->imag-c.imag);
}

myComplex myComplex::operator-(double r)
{
    return myComplex(this->real-r,this->imag);
}

int main()
{
    myComplex c1(1,2),c2(3,4),res;
    c1.outCom();
    cout<<"operator-";
    c2.outCom();
    cout<<"=";
    res = c1 - 2;   //正确
//  res = 2 - c1;   //错误,不能实现 
    res.outCom();
    cout<<endl;
    return 0;
}

(1,2)operator-(3,4)=(-1,2)

例4-2 重载为友元函数

#include <iostream>
using namespace std;

class myComplex     //复数类 
{
    private:
        double real,imag;
    public:
        myComplex();
        myComplex(double r,double i);
        void outCom();
        myComplex operator-(const myComplex &c);
        friend myComplex operator+(const myComplex &c1,const myComplex &c2);
        friend myComplex operator-(const myComplex &c1,const myComplex &c2);
        friend myComplex operator-(const myComplex &c1,double r);
        friend myComplex operator-(double r,const myComplex &c1);
};

myComplex::myComplex()
{
    real = 0;
    imag = 0;
}

myComplex::myComplex(double r,double i)
{
    real = r;
    imag = i;
}

void myComplex::outCom()
{
    cout<<"("<<real<<","<<imag<<")";
}

myComplex myComplex::operator-(const myComplex &c)
{
    return myComplex(this->real-c.real,this->imag-c.imag);
}

myComplex operator+(const myComplex &c1,const myComplex &c2)
{
    return myComplex(c1.real + c2.real,c1.imag + c2.imag);
}

myComplex operator-(const myComplex &c1,const myComplex &c2)
{
    return myComplex(c1.real - c2.real,c1.imag - c2.imag);
}

myComplex operator-(const myComplex &c1,double r)
{
    return myComplex(c1.real - r,c1.imag);
}

myComplex operator-(double r,const myComplex &c1)
{
    return myComplex(r - c1.real,-c1.imag);
}

int main()
{
    myComplex c1(1,2),c2(3,4),res;
    res = c1 + c2;
    res.outCom();
    res = c1 - 5;
    res.outCom();
    res = 5 - c1;
    res.outCom();
    
    
    return 0;
}

(4,6)(-4,2)(4,-2)

重载运算符的规则

在C++中进行运算符重载时,有以下规则:

  • 重载后运算符的含义应该符合原有的用法习惯。
  • 运算符重载不能改变运算符原有的语义,包括运算符的优先级和结合性。
  • 运算符重载不能改变运算符操作数的个数及语法结构。
  • 不能创建新的运算符,即重载运算符不能超出C++语言允许重载的运算符范围。
  • 重载运算符() [] ->或者赋值运算符=时,只能将它们重载为成员函数,不能重载为全局函数。
  • 运算符重载不能改变该运算符用于基本数据类型对象的含义。

二、重载赋值运算符

重载赋值运算符

C++中的赋值运算符“=”要求左右两个操作数的类型时匹配的,或至少是赋值兼容的。

C++规定,“=”只能重载为成员函数。

程序4-2 为类myComplex重载赋值运算符

#include <iostream>
using namespace std;

class myComplex     //复数类 
{
    private:
        double real,imag;
    public:
        myComplex();
        myComplex(double r,double i);
        ~myComplex(){}
        myComplex addCom(myComplex c1); //成员函数,调用对象与参数对象c1相加 
        void outCom();
        void outCom(string s);
        void changeReal(double r);  //成员函数
        friend myComplex operator+(const myComplex &c1,const myComplex &c2);    //c1+c2
        friend myComplex operator+(const myComplex &c1,double r);       //c1+r
        friend myComplex operator+(double r,const myComplex &c1);       //r+c1
        friend myComplex operator-(const myComplex &c1,const myComplex &c2);    //c1-c2
        friend myComplex operator-(const myComplex &c1,double r);       //c1-r
        friend myComplex operator-(double r,const myComplex &c1);       //r-c1
        myComplex &operator=(const myComplex &c);       //成员函数 
        myComplex &operator=(double);       //成员函数 
};

myComplex::myComplex()
{
    real = 0;
    imag = 0;
}

myComplex::myComplex(double r,double i)
{
    real = r;
    imag = i;
}

myComplex myComplex::addCom(myComplex c1)
{
    return myComplex(this->real + c1.real,this->imag + c1.imag);
 } 

void myComplex::outCom()
{
    cout<<"("<<real<<","<<imag<<")";
}

void myComplex::outCom(string s)
{
    cout<<s<<"=("<<real<<","<<imag<<")"<<endl;
}

void myComplex::changeReal(double r)
{
    this->real=r;
}

myComplex operator+(const myComplex &c1,const myComplex &c2)  //c1+c2
{
    return myComplex(c1.real + c2.real,c1.imag + c2.imag);  //返回一个临时对象 
}

myComplex operator+(const myComplex &c1,double r)   //c1+r
{
    return myComplex(c1.real + r,c1.imag);
}


myComplex operator+(double r,const myComplex &c1)       //r+c1
{
    return myComplex(r+c1.real,c1.imag);
}

myComplex operator-(const myComplex &c1,const myComplex &c2)    //c1-c2
{
    return myComplex(c1.real - c2.real,c1.imag - c2.imag);
}

myComplex operator-(const myComplex &c1,double r)   //c1-r
{
    return myComplex(c1.real- r,c1.imag);
}


myComplex operator-(double r,const myComplex &c1)       //r-c1
{
    return myComplex(r-c1.real,-c1.imag);
}

myComplex &myComplex::operator=(const myComplex &c1)
{
    this->real = c1.real;
    this->imag = c1.imag;
    return *this;
}

myComplex &myComplex::operator = (double r)
{
    this->real = r;
    this->imag = 0;
    return *this;
}


int main()
{
    myComplex c1(1,2),c2(3,4),res;
    c1.outCom("\t\tc1");
    c2.outCom("\t\tc2");
    res = c1 + c2;
    res.outCom("执行res=c1+c2→\tres");
    res = c1.addCom(c2);
    res.outCom("执行res=c1.addCom(c2)→\tres");
    res = c1 + 5;
    res.outCom("执行res=c1 + 5→\tres");
    res = 5 + c1;
    res.outCom("执行res=5 + c1→\tres");
    
    res = c1;
    c1.outCom("\t\tc1");
    res.outCom("执行res=c1→\tres");
    
    c1.changeReal(-3);
    c1.outCom("执行c1.changeReal(-3)→\tc1");
    
    res.outCom("\t\tres");
    res = c1;
    res.outCom("执行res=c1→\tres");
    
    res = 7;
    res.outCom("执行res=7→\tres");
    
    res = 7+8;
    res.outCom("执行res=(7+8)→\tres");
    
    res= c1 = c2;
    c1.outCom("\t\tc1");
    c2.outCom("\t\tc2");
    res.outCom("执行res=c1=c2→\tres");
    return 0;
}

                c1=(1,2)
                c2=(3,4)
执行res=c1+c2→ res=(4,6)
执行res=c1.addCom(c2)→ res=(4,6)
执行res=c1 + 5→        res=(6,2)
执行res=5 + c1→        res=(6,2)
                c1=(1,2)
执行res=c1→    res=(1,2)
执行c1.changeReal(-3)→ c1=(-3,2)
                res=(1,2)
执行res=c1→    res=(-3,2)
执行res=7→     res=(7,0)
执行res=(7+8)→ res=(15,0)
                c1=(3,4)
                c2=(3,4)
执行res=c1=c2→ res=(3,4)

关于重载赋值运算符应注意

  • 赋值运算符必须重载为成员函数
  • 为了保持与通常意义下的赋值运算符的功能相一致,应该让重载的赋值运算符能连续使用。

浅拷贝和深拷贝

同类对象之间可以通过赋值运算符“=”互相赋值。如果没有经过重载,“=”的作用就是将赋值号右侧对象的值一一赋值给左侧的对象。这相当于值的拷贝,称为“浅拷贝”。

程序4-3 浅拷贝的含义

#include <iostream>
using namespace std;

class pointer
{
    public:
        int a;
        int *p;
        pointer()
        {
            a = 100;
            p = new int(10);
        }
        pointer(const pointer &tempp)
        {
            if(this != &tempp)
            {
                a = tempp.a;
                p = tempp.p;
            }
        }
};

int main()
{
    pointer p1;
    pointer p2(p1); //使用复制构造函数 
    pointer p3 = p1;    //使用复制构造函数 
    cout<<"\n初始化后,各对象的值及内存地址:"<<endl;
    cout<<"对象名\t对象地址        a的值     p中的值        p指向的值       p的地址"<<endl;
    cout<<"p1:\t"<<&p1<<",      "<<p1.a<<",     "<<p1.p<<",     "<<*p1.p<<",        "<<&p1.p<<endl;
    cout<<"p2:\t"<<&p2<<",      "<<p2.a<<",     "<<p2.p<<",     "<<*p2.p<<",        "<<&p2.p<<endl;
    cout<<"p3:\t"<<&p3<<",      "<<p3.a<<",     "<<p3.p<<",     "<<*p3.p<<",        "<<&p3.p<<endl;
    
    *p1.p = 20;
    p2.a = 300;
    cout<<"\n修改后,各对象的值及内存地址:"<<endl;
    cout<<"对象名\t对象地址        a的值     p中的值        p指向的值       p的地址"<<endl;
    cout<<"p1:\t"<<&p1<<",      "<<p1.a<<",     "<<p1.p<<",     "<<*p1.p<<",        "<<&p1.p<<endl;
    cout<<"p2:\t"<<&p2<<",      "<<p2.a<<",     "<<p2.p<<",     "<<*p2.p<<",        "<<&p2.p<<endl;
    cout<<"p3:\t"<<&p3<<",      "<<p3.a<<",     "<<p3.p<<",     "<<*p3.p<<",        "<<&p3.p<<endl;
    return 0; 
}

初始化后,各对象的值及内存地址:
对象名  对象地址                a的值           p中的值         p指向的值               p的地址
p1:     0x6ffdf0,               100,            0x891500,               10,             0x6ffdf8
p2:     0x6ffde0,               100,            0x891500,               10,             0x6ffde8
p3:     0x6ffdd0,               100,            0x891500,               10,             0x6ffdd8

修改后,各对象的值及内存地址:
对象名  对象地址                a的值           p中的值         p指向的值               p的地址
p1:     0x6ffdf0,               100,            0x891500,               20,             0x6ffdf8
p2:     0x6ffde0,               300,            0x891500,               20,             0x6ffde8
p3:     0x6ffdd0,               100,            0x891500,               20,             0x6ffdd8

重载赋值运算符后,赋值语句的功能是将一个对象中指针成员变量指向的内容复制到另一个对象中指针成员变量指向的地方,这样的拷贝叫“深拷贝”。
程序4-4 深拷贝的实现

#include <iostream>
using namespace std;
class pointer
{
    public:
        int a;
        int *p;
        pointer()
        {
            a = 100;
            p = new int(10);
        }
        pointer(const pointer &tempp)
        {
            if(this != &tempp)
            {
                a = tempp.a;
                p = tempp.p;
                *p = *tempp.p;
            }
        }
        ~pointer()
        {
            if(p != NULL)delete p;
        }
        pointer &operator=(const pointer &c)
        {
            if(this == &c)return *this;
            delete this->p;
            this->p = new int(*c.p);
            return *this;
        }
};

int main()
{
    pointer p1;
    pointer p2(p1); //使用复制构造函数 
    pointer p3;
    p1 = p1;
    p3 = p1;
    cout<<"\n初始化后,各对象的值及内存地址:"<<endl;
    cout<<"对象名\t对象地址        a的值     p中的值        p指向的值       p的地址"<<endl;
    cout<<"p1:\t"<<&p1<<",      "<<p1.a<<",     "<<p1.p<<",     "<<*p1.p<<",        "<<&p1.p<<endl;
    cout<<"p2:\t"<<&p2<<",      "<<p2.a<<",     "<<p2.p<<",     "<<*p2.p<<",        "<<&p2.p<<endl;
    cout<<"p3:\t"<<&p3<<",      "<<p3.a<<",     "<<p3.p<<",     "<<*p3.p<<",        "<<&p3.p<<endl;
    
    *p1.p = 20;
    p2.a = 300;
    cout<<"\n修改后,各对象的值及内存地址:"<<endl;
    cout<<"对象名\t对象地址        a的值     p中的值        p指向的值       p的地址"<<endl;
    cout<<"p1:\t"<<&p1<<",      "<<p1.a<<",     "<<p1.p<<",     "<<*p1.p<<",        "<<&p1.p<<endl;
    cout<<"p2:\t"<<&p2<<",      "<<p2.a<<",     "<<p2.p<<",     "<<*p2.p<<",        "<<&p2.p<<endl;
    cout<<"p3:\t"<<&p3<<",      "<<p3.a<<",     "<<p3.p<<",     "<<*p3.p<<",        "<<&p3.p<<endl;
    return 0; 
}

初始化后,各对象的值及内存地址:
对象名  对象地址                a的值           p中的值         p指向的值               p的地址
p1:     0x6ffdf0,               100,            0x171500,               10,             0x6ffdf8
p2:     0x6ffde0,               100,            0x171500,               10,             0x6ffde8
p3:     0x6ffdd0,               100,            0x171520,               10,             0x6ffdd8

修改后,各对象的值及内存地址:
对象名  对象地址                a的值           p中的值         p指向的值               p的地址
p1:     0x6ffdf0,               100,            0x171500,               20,             0x6ffdf8
p2:     0x6ffde0,               300,            0x171500,               20,             0x6ffde8
p3:     0x6ffdd0,               100,            0x171520,               10,             0x6ffdd8

三、重载流插入运算符和流提取运算符

在C++中,左移运算符“<<”可以和cout一起用于输出,故常被称为“流插入运算符”。

右移运算符“>>”和cin一起用于输入,称为“流提取运算符”。

流是标准库,用户程序中只能继承不能修改,所以重载函数不能是流类库中的成员,而必须重载为类的友元。
重载流插入运算符的一般格式

ostream &operator<<(ostream & output,类名&对象名)
{
  ...
  return output;
}

重载流提取运算符的一般格式

istream &operator>>(istream & input,类名&对象名)
{
  ...
  return input;
}

程序4-5 流插入运算符和流提取运算符重载为友元

#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;

class myComplex
{
    private:
        double real,imag;
    public:
        myComplex():real(0),imag(0){}
        myComplex(double r,double i):real(r),imag(i){}
        friend ostream &operator<<(ostream &os,const myComplex & c);
        friend istream &operator>>(istream &is,myComplex &c);
};

ostream & operator<<(ostream &os,const myComplex &c)
{
    if(c.imag >=0)
    {
        os<<c.real<<"+"<<c.imag<<"i";
    }else
    {
        os<<c.real<<"-"<<(-c.imag)<<"i";
    }
    return os;
}

istream & operator >>(istream &is,myComplex &c)
{
    string s;
    is>>s;      //将a+bi作为字符串读入,a+bi中间不能有空格
    int pos = s.find("+",0);    //查找虚部
    if(pos == -1)pos = s.find("-",1);       //虚部为复数时
    string sReal = s.substr(0,pos); //分离出代表实部的字符串
    c.real = atof(sReal.c_str());   //atof()能将参数内容转换成浮点数
    sReal = s.substr(pos,s.length()-pos-1); //分离出代表虚部的字符串
    c.imag = atof(sReal.c_str());
    return is; 
}

int main()
{
    myComplex c,c1;
    int n;
    cout<<"请输入两个复数([-]a±bi)和一个整数,以空格分隔"<<endl;
    cin>>c>>c1>>n;
    cout<<c<<","<<n<<","<<c1;
    return 0; 
}

请输入两个复数([-]a±bi)和一个整数,以空格分隔
3.4-3i -5+6i 36
3.4-3i,36,-5+6i

程序4-6 流插入运算符重载为成员函数

#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;

class myComplex
{
    private:
        double real,imag;
    public:
        myComplex():real(0),imag(0){}
        myComplex(double r,double i):real(r),imag(i){}
        ostream &operator<<(ostream &os);
        friend istream &operator>>(istream &is,myComplex &c);
};

ostream & myComplex::operator<<(ostream &os)
{
    if(this->imag >=0)
    {
        os<<this->real<<"+"<<this->imag<<"i";
    }else
    {
        os<<this->real<<"-"<<(-this->imag)<<"i";
    }
    return os;
}

istream & operator >>(istream &is,myComplex &c)
{
    string s;
    is>>s;      //将a+bi作为字符串读入,a+bi中间不能有空格
    int pos = s.find("+",0);    //查找虚部
    if(pos == -1)pos = s.find("-",1);       //虚部为复数时
    string sReal = s.substr(0,pos); //分离出代表实部的字符串
    c.real = atof(sReal.c_str());   //atof()能将参数内容转换成浮点数
    sReal = s.substr(pos,s.length()-pos-1); //分离出代表虚部的字符串
    c.imag = atof(sReal.c_str());
    return is; 
}

int main()
{
    myComplex c,c1;
    int n;
    cout<<"请输入两个复数([-]a±bi)和一个整数,以空格分隔"<<endl;
    cin>>c>>c1>>n;
    c1<<(c<<cout<<",")<<","<<n;
    return 0; 
}

请输入两个复数([-]a±bi)和一个整数,以空格分隔
3.4-3i -5+6i 36
3.4-3i,-5+6i,36

*四、重载强制类型转换运算符

在C++中,类型的名字(包括类的名字)本身意识一种运算符,即强制类型转换运算符。

强制类型转换运算符是单目运算符,也可以被重载,但只能重载为成员函数,不能重载为全局函数。

程序4-7 重载强制类型转换运算符double

#include <iostream>
using namespace std;

class myComplex
{
    double real,imag;
    public:
        myComplex(double r=0,double i=0):real(r),imag(i){}
        operator double()
        {
            return real;
        }
};

int main()
{
    myComplex c(1.2,-3.4);
    cout<<(double)c<<endl;
    double n = 12+c;
    cout<<n;
    return 0;
}

1.2
13.2

五、重载自增、自减运算符

自增运算符“++”和自减运算符“--”都可以被重载,但是它们有前置和后置之分。

运算符重载相当于定义了一个以运算符为名字的函数。以自增运算符为例,可以表示为:

CDemo & CDemo::operator++()
{
  ...
  return *this;
}

这样的函数不能区分前置及后置情况。

C++规定,在重载“++”或“--”时,允许写一个增加了无用int类型形参的版本,编译器处理“++”或“--”前置的表达式时,调用参数个数正常的重载函数;处理后置的表达式时,调用多出一个参数的重载函数。

程序4-8 自增运算符重载为成员函数,自减运算符重载为友元。

#include <iostream>
using namespace std;

class CDemo
{
    private:
        int n;
    public:
        CDemo(int i = 0):n(i){}
        CDemo & operator++();       //用于前置形式
        CDemo & operator++(int);    //用于后置形式
        operator int() {return n;}
        friend CDemo & operator--(CDemo &);
        friend CDemo operator--(CDemo &,int);
};

CDemo & CDemo::operator++()     //前置++ 
{
    n++;
    return *this;
}

CDemo & CDemo::operator++(int k)    //后置++,多一个参数 
{
    CDemo tmp(*this);       //记录修改前的对象 
    n++;
    return tmp;         //返回修改前的对象 
}

CDemo & operator--(CDemo & d)   //前置-- 
{
    d.n--;
    return d;
}

CDemo operator--(CDemo & d,int)     //后置-- 
{
    CDemo tmp(d);
    d.n--;
    return tmp; 
 } 
 
int main()
{
    CDemo d(10);
    cout<<"(d++)="<<(d++)<<",";     //等价于“d.operator++(0);”输出10
    cout<<"\nd="<<d<<",";           //输出11 
    cout<<"\n(++d)="<<(++d)<<",";       //等价于“d.operator++();”输出12
    cout<<"\nd="<<d<<",";               //输出12
    cout<<"\n(d--)="<<(d--)<<",";       //等价于“d.operator--(0);”输出12
    cout<<"\nd="<<d<<",";               //输出11
    cout<<"\n(--d)="<<(--d)<<",";       //等价于“d.operator--();”输出10
    cout<<"\nd="<<d<<endl;              //输出10
    return 0;
}


(d++)=10,
d=11,
(++d)=12,
d=12,
(d--)=12,
d=11,
(--d)=10,
d=10

程序4-9 自增、自减运算符重载为成员函数

#include <iostream>
using namespace std;

class CDemo
{
    private:
        int n;
    public:
        CDemo(int i = 0):n(i){}
        CDemo & operator++();       //用于前置形式
        CDemo & operator++(int);    //用于后置形式
        operator int()
        {
            return n;
        }
        CDemo & operator--();
        CDemo operator--(int);
};

CDemo & CDemo::operator++()     //前置++ 
{
    n++;
    return *this;
}

CDemo & CDemo::operator++(int k)    //后置++,多一个参数 
{
    CDemo tmp(*this);       //记录修改前的对象 
    n++;
    return tmp;         //返回修改前的对象 
}

CDemo & CDemo::operator--() //前置-- 
{
    n--;
    return *this;
}

CDemo CDemo::operator--(int k)      //后置-- 
{
    CDemo tmp(*this);
    n--;
    return tmp; 
 } 
 
int main()
{
    CDemo d(10);
    cout<<"(d++)="<<(d++)<<",";     //等价于“d.operator++(0);”输出10
    cout<<"\nd="<<d<<",";           //输出11 
    cout<<"\n(++d)="<<(++d)<<",";       //等价于“d.operator++();”输出12
    cout<<"\nd="<<d<<",";               //输出12
    cout<<"\n(d--)="<<(d--)<<",";       //等价于“d.operator--(0);”输出12
    cout<<"\nd="<<d<<",";               //输出11
    cout<<"\n(--d)="<<(--d)<<",";       //等价于“d.operator--();”输出10
    cout<<"\nd="<<d<<endl;              //输出10
    return 0;
}

(d++)=10,
d=11,
(++d)=12,
d=12,
(d--)=12,
d=11,
(--d)=10,
d=10
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 227,428评论 6 531
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 98,024评论 3 413
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 175,285评论 0 373
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 62,548评论 1 307
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 71,328评论 6 404
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 54,878评论 1 321
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 42,971评论 3 439
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,098评论 0 286
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 48,616评论 1 331
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 40,554评论 3 354
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 42,725评论 1 369
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,243评论 5 355
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 43,971评论 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,361评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 35,613评论 1 280
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 51,339评论 3 390
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 47,695评论 2 370

推荐阅读更多精彩内容

  • 运算符重载的概念 C++中的表达式由运算符和操作数按照规则构成。例如,算术运算符包括加+、减-、乘*、除/和取模%...
    silasjs阅读 708评论 0 1
  • 运算符重载 运算符重载的概念 在C++中,基本的算数运算符,如果不做特殊处理,则 不能用于对象之间的运算 。 运算...
    陈_MY阅读 457评论 0 0
  • 基本概念 重载的运算符本质上是具有特殊名字的函数,名字由关键字operator和后面要定义的运算符号共同组成。该函...
    Kreat阅读 361评论 0 0
  • 01 运算符重载的需求 C++ 预定义的运算符,只能用于基本数据类型的运算:整型、实型、字符型、逻辑型等等,且不能...
    小林coding阅读 268评论 0 0
  • 技术交流QQ群:1027579432,欢迎你的加入! 1.Cpp中的重载运算符和重载函数 C++允许在同一作用域中...
    CurryCoder阅读 513评论 0 1