C++运算符重载

运算符重载

C++将运算符重载扩展到自定义的数据类型,它可以让对象操作更美观。
例如字符串string用加号(+)拼接,cout用两个左尖括号(<<)输出。

语法:返回值 operator 运算符(参数列表)
非成员函数版本的重载运算符函数:形参个数与运算符操作数个数相同;
成员函数版本的重载运算符函数:形参个数比运算符的操作数个数少一个,其中一个操作数隐式传递了调用对象。

一、重载‘+’运算符

1.非成员函数版本重载

#include<iostream>
using namespace std;
class CStudent
{
   
    public:
    int score;
    int ID;
    CStudent(){
   score=80;ID=0;}
    void show(){
   cout<<"ID:"<<ID<<endl;cout<<"分数:"<<score<<endl;}
};
void operator+(CStudent &s,int a)
{
   
    s.score=s.score+a;
}
int main()
{
   
    CStudent s;
    operator+(s,1);
    s.show();
    s+2;
    s.show();
    return 0;
}

执行结果:
在这里插入图片描述

空返回值的运算符重载有个弊端,就是在同一条语句下不能连续使用,如:
在这里插入图片描述
如果需要在同一条语句中连续使用,返回值类型不能为空。如下所示:

#include<iostream>
using namespace std;
class CStudent
{
   
    public:
    int score;
    int ID;
    CStudent(){
   score=80;ID=0;}
    void show(){
   cout<<"ID:"<<ID<<endl;cout<<"分数:"<<score<<endl;}
};
CStudent& operator+(CStudent &s,int a)//返回值类型不为空
{
   
    s.score=s.score+a;
    return s;
}
int main()
{
   
    CStudent s;
    operator+(s,1);
    s.show();
    s+2+3 ;
    s.show();
    return 0;
}

执行结果:
在这里插入图片描述

2.成员函数版本

看下面的例子:
在这里插入图片描述
说明:成员函数运算符重载里只能有一个参数。

对于+号运算符来说,类外运算符重载和运算符重载同时存在时,系统会不知道调用哪一个,所以要去掉类外运算符重载。
在这里插入图片描述


#include<iostream>
using namespace std;
class CStudent
{
   
    public:
    int score;
    int ID;
    CStudent(){
   score=80;ID=0;}
    void show(){
   cout<<"ID:"<<ID<<endl;cout<<"分数:"<<score<<endl;}
    void operator+(int b){
   this->score=this->score+b;}
};
// CStudent& operator+(CStudent &s,int a)
// {
   
//     s.score=s.score+a;
//     return s;
// }
int main()
{
   
    CStudent s;
    s.operator+(1);
    s.show();
    s+5;
    s.show();
    return 0;
}

执行结果:
在这里插入图片描述

同理,返回值类型为void 时,运算符在同一条语句中不能连用,需将返回值返回一个对象引用

#include<iostream>
using namespace std;
class CStudent
{
   
    public:
    int score;
    int ID;
    CStudent(){
   score=80;ID=0;}
    void show(){
   cout<<"ID:"<<ID<<endl;cout<<"分数:"<<score<<endl;}
    CStudent& operator+(int b){
   this->score=this->score+b;return *this;}
};
int main()
{
   
    CStudent s;
    (s.operator+(1)).operator+(2);
    s.show();
    s+5+2;
    s.show();
    return 0;
}

执行结果:
在这里插入图片描述

注意事项:
返回自定义数据类型的引用可以让多个运算符表达式串联起来。(不要返回局部变量的引用)
重载函数参数列表中的顺序决定了操作数的位置。
重载函数的参数列表中至少有一个是用户自定义的类型,防止程序员为内置数据类型重载运算符。
如果运算符重载既可以是成员函数也可以是全局函数,应该优先考虑成员函数,这样更符合运算符重载的初衷。
重载函数不能违背运算符原来的含义和优先级。
不能创建新的运算符。

以下运算符只通过成员函数进行重载:
= 赋值运算符
()函数调用运算符
[]下标运算符
->通过指针访问类成员的运算符

二、重载关系运算符

关系运算符有:==、!=、>、>=、<、<=用于比较两个自定义数据类型的大小。重载关系运算符时尽量使用成员函数版本。

#include<iostream>
using namespace std;
class CStudent{
   
    public:
    string name;
    int chinese;
    int math;
    int english;
    CStudent(string s_name,int s_chinese, int s_math, int m_english):
    name(s_name),chinese(s_chinese),math(s_math),english(m_english)
    {
   }
    bool operator==(CStudent &rhs)
    {
   
        if((this->chinese+this->math+this->english)==(rhs.chinese+rhs.english+rhs.math))
        return true;
        return false;
    }
};
int main()
{
   
    CStudent s1("李华",85,92,95);
    CStudent s2("李明",82,94,96);
    if(s1==s2)
    {
   
        cout<<"李华和李明成绩一样!"<<endl;
    }
    else
    cout<<"李华和李明成绩不一样!"<<endl;
    return 0;
}

执行结果:
在这里插入图片描述

三、重载左移运算符

重载左移运算符(<<)用于输出自定义对象的成员变量,在实际开发中很有价值(调试和日志) 只能使用非成员函数版本。
如果输出对象的私有成员,可以配合友元一起使用。

语法:

ostream& operator<<(ostream& cout,constant type& rhs)
{
   
cout<<rhs.xxx<<……<<endl;
return cout;
}

示例:

#include<iostream>
using namespace std;
class CStudent{
   
    public:
    string name;
    int chinese;
    int math;
    int english;
    CStudent(string s_name,int s_chinese, int s_math, int m_english):
    name(s_name),chinese(s_chinese),math(s_math),english(m_english)
    {
   }
    
};
ostream &operator<<(ostream& cout,const CStudent&s)
{
   
    cout<<"姓名:"<<s.name<<"\n语文成绩:"<<s.chinese<<"\n数学成绩:"<<s.math<<"\n英语成绩:"<<s.english<<endl;
    return cout;
}
int main()
{
   
   CStudent s("小明",88,79,92);
   cout<<s;
   return 0;
} 

运行结果:
在这里插入图片描述

四、重载下标运算符

如果对象中有数组,重载下标运算符[],操作对象中的数组将像操作普通数组一样方便。
下标运算符必须以成员函数的形式进行重载。

语法:
返回值类型 &operator 或者:const 返回值类型 &operator[](参数)const
使用第一种声明方式,[]不公可以访问数组元素,还可以修改数组元素。 使用第二种声明方式,[]只能访问不能修改数组元素。
在实际开发中,两种都要提供,目的是为了迁就常对象,因为常对象不能访问非常函数。

看下面的例子:

#include<iostream>
using namespace std;
class CStudent{
   
    public:
    string name;
    int chinese;
    int math;
    int english;
    string friends[3];
    CStudent(string s_name,int s_chinese, int s_math, int m_english):
    name(s_name),chinese(s_chinese),math(s_math),english(m_english)
    {
   
        friends[0]="小华";
        friends[1]="小红";
        friends[2]="小方";
    }
    string &operator[](int i)
    {
   
        return this->friends[i];
    }
    
};

int main()
{
   
   const CStudent s("小明",88,79,92);
   cout<<s[2]<<endl;
   return 0;
} 

执行结果:
在这里插入图片描述
结论:常对象不能访问非常成员函数

#include<iostream>
using namespace std;
class CStudent{
   
    public:
    string name;
    int chinese;
    int math;
    int english;
    string friends[3];
    CStudent(string s_name,int s_chinese, int s_math, int m_english):
    name(s_name),chinese(s_chinese),math(s_math),english(m_english)
    {
   
        friends[0]="小华";
        friends[1]="小红";
        friends[2]="小方";
    }
    string &operator[](int i)
    {
   
        return this->friends[i];
    }
    
};

int main()
{
   
   CStudent s("小明",88,79,92);
   cout<<s[2]<<endl;
   return 0;
} 

执行结果:
在这里插入图片描述


#include<iostream>
using namespace std;
class CStudent{
   
    public:
    string name;
    int chinese;
    int math;
    int english;
    string friends[3];
    CStudent(string s_name,int s_chinese, int s_math, int m_english):
    name(s_name),chinese(s_chinese),math(s_math),english(m_english)
    {
   
        friends[0]="小华";
        friends[1]="小红";
        friends[2]="小方";
    }
     string &operator[](int i)
    {
   
        return this->friends[i];
    }
};

int main()
{
   
   CStudent s("小明",88,79,92);
   s[2]="小北";
   cout<<s[2]<<endl;
   return 0;
} 

执行结果:
在这里插入图片描述> 说明:可以通过重载下标运算符来访问和修改成员变量。

#include<iostream>
using namespace std;
class CStudent{
   
    public:
    string name;
    int chinese;
    int math;
    int english;
    string friends[3];
    CStudent(string s_name,int s_chinese, int s_math, int m_english):
    name(s_name),chinese(s_chinese),math(s_math),english(m_english)
    {
   
        friends[0]="小华";
        friends[1]="小红";
        friends[2]="小方";
    }
    const string &operator[](int i)//表示返回值不允许修改
    {
   
        return this->friends[i];
    }
};

int main()
{
   
   CStudent s("小明",88,79,92);
   s[2]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值