C++运算符重载


【全文大纲】 : https://blog.csdn.net/Engineer_LU/article/details/135149485


前言

  1. 有时候为了更方便对象内存交互,因此诞生了运算符重载,可以让对象的内存之间进行加减乘除等运算,以下深入浅出描述C++运算符重载
  2. 运算符重载的本质是函数

1 . 运算符重载-限制

  1. 可重载的运算符 :
+-*/%^&
|~!=<>+=
-=*=/=%=^=&==
<<>>>>=<<===!=<=
>=&&||++->*
->[]()newdeletenew[]delete[]
  1. 不可重载的运算符 :
.::.*?:sizeof

其中下面四个运算符不可在全局函数中重载

=[]->()

其中下面这个运算符重载由于其左值必须为osteam类,因此只能重载为友元函数

<<
  • 小结 :C++大部分运算符可以重载

2 . 运算符重载-差异

运算符重载前运算符重载后
优先级不变不变
结合性不变不变
语意不变改变
  • 小结 :重载只会让语意改变,其余不变

3 . 运算符重载-语法

成员函数返回值类型 类名 :: operator 运算符 ( 参数列表 ){ }
全局函数返回值类型 operator opa( 参数列表 ){ }
  • 小结 :两者语法基本一致

4 . 运算符重载-例子

1 . 在C++中,可以看到 cout << “Hello World”; 这样的写法如下图,为什么这样可以过编译呢?实际上 coutostream 类的对象,能在对象 cout 后面加上 << 是因为 ostream 这个类对 << 该运算符执行了重载的逻辑,而上述提到重载本质是函数,因此可以基于传入参数列表的内容与对象 cout 内的成员进行交互。

cout << "Hello World"; //编译后,cout内的 operator<<() 运算符重载函数被调用

2 . 下图是 成员运算符重载全局运算符重载 的例子
人类a的年龄28岁,有150块,人类b的年龄22,有50块
通过全局运算符重载把这两个人的年龄相加得出50岁,金钱相加得出200块
通过成员运算符重载把这两个人的年龄相减得出6岁,金钱相减得出100块

  • 全局运算符重载 的参数列表中引入两个对象参与运算,把两个具体的对象引入参与运算
  • 成员运算符重载 的参数列表中引入一个对象参与运算,把引入的对象与运算符重载的 左值对象 参与运算 (隐式调用)
#include <iostream>
using namespace std;

class People {
public:
    double age, money;
    People():age(0),money(0) {}
    People(double a, double m):age(a),money(m){}
    People operator-(const People& f);
};
//重载运算符+ (重载为普通函数)
People operator+ (const People& a, const People& b)
{
    return People(a.age + b.age, a.money + b.money); //返回一个临时对象
}
//重载运算符- (重载为成员函数)
People People::operator-(const People& p)
{
    return People(age - p.age, money - p.money);	//返回一个临时对象
}

int main()
{
    People a(28, 150), b(22, 50), c;

    c = a + b; //等同 c = operator+(a, b);
    cout << c.age << c.money;//结果 50, 200

    uint16_t age = (a - b).age; //等同a.operator-(b).age
    uint16_t money = (a - b).money;
    cout << age << money;//结果 6, 100

    return 0;
}

3 . 既然运算符重载分为 成员运算符重载全局运算符重载 ,全局运算符重载怎么访问类里的隐私数据,这里可以在类中把全局运算符重载声明为友元函数,这样全局运算符重载就可以访问类里的隐私数据,如下图,把 People operator+ (const People& a, const People& b) 声明为友元函数
【Q】这里可能有疑问,那把运算符重载函数全部塞到类里不就好了吗?
【A】上述提到有一些情况只能通过友元函数关联起来,例如 << 该运算符的特殊情况,因此勿要把运算符重载函数全部塞到类里

class People {
public:
    double age, money;
    People():age(0),money(0) {}
    People(double a, double m):age(a),money(m){}
    People operator-(const People& f);
    friend People operator+(const People& f);
};
//重载运算符+ (重载为普通函数)
People operator+ (const People& a, const People& b)
{
    return People(a.age + b.age, a.money + b.money); //返回一个临时对象
}
//重载运算符- (重载为成员函数)
People People::operator-(const People& p)
{
    return People(age - p.age, money - p.money);	//返回一个临时对象
}

4 . 运算符重载的妙处还有很多,如下图,运算符 = 两边的类型不一致时,又想让两边内存参与运算,这时候只需要把 = 重载, = 该运算符只能在成员函数中重载,因为如果是全局,那程序中很多类型赋值时检索,就会在赋予地址产生冲突,但若是在成员中重载,那仅仅相应的对象运算时才会重载,不会冲突

#include <iostream>
using namespace std;

class People {
public:
    double age, money;
    People():age(0),money(0) {}
    People(double a, double m):age(a),money(m){}

    uint16_t operator=(uint16_t m) {
        return m + money;
    }
};

int main()
{
    People a(28, 150);

    int memory = 10;
    cout << (a = memory);

    return 0;
}

5 . 运算符重载-触发

经过上述例子和规则描述,可以总结出当写了运算符重载后

  • 当有全局运算符重载时就会检索相应运算符的 左值 右值,当左右都符合参数列表则执行运算符重载函数,
  • 当有成员运算符重载时就会检索相应运算符的 左值,当左值的对象内有运算符重载触发检测,配对右值的类型,符合则执行运算符重载函数

6 . 总结

1 . 遵循原运算符语意扩展,即+运算,扩展后遵循+的逻辑交互内存
2 . 大部分运算符可以重载,小部分不可以(如上述描述)
3 . 个别运算符仅能在成员中重载
4 . 个别运算符仅能在全局中重载
5 . 运算符重载触发机制取决于是否属于全局/成员,参数列表是否符合

以上关于运算符重载的总结,谢谢观看。

技术交流QQ群 : 745662457
群内专注 - 问题答疑,项目外包,技术研究

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

极客 - L U

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

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

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

打赏作者

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

抵扣说明:

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

余额充值