当前位置: 首页 > news >正文

【C++】类和对象--类中6个默认成员函数(2) --运算符重载

目录

问题引入

1. 运算符重载


问题引入

在C++中,我们之前讲过了,一个类中什么都没有,我们将其称作空类。但是我们之前提到过,就算我们在类中什么也不定义,编译器会自动生成6个默认的成员函数:构造函数、析构函数、拷贝构造函数、赋值重载,以及两个取地址。

我们本篇重点介绍的就是赋值重载函数。如果我们定义了两个日期类Date d1、d2,如果我想要比较两个对象的大小,我应该怎么办呢?这里就要重点讲到今天的知识:运算符重载。

1. 运算符重载

为了增强代码的可读性,C++中引入了运算符重载的概念,运算符重载是一种有着特殊函数名的函数:

  • 函数名字:关键字operator + 需要重载的运算符符号
  • 函数原型返回值类型 operator 操作符(参数列表)

我们接下来使用一个Date类来进行说明:

class Date
{
public:Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}
private:int _year;int _month;int _day;
};int main()
{Date d1(2025, 8, 6);Date d2(2025, 8, 6);if (d1 == d2){cout << "==" << endl;}return 0;
}

我们正常的想法,不就是通过运算符==来比较两个变量的大小嘛,那么上面的代码能不能正常运行呢?

答案是:不行的

原因:只有内置类型的变量才能使用各种运算符,对于Date这种我们自定义类型的的对象是不能直接使用的。而为了是的自定义类型对象能够使用这些运算符,C++给出了运算符重载的概念。

注意:这里的运算符重载和之前我们学习的函数重载是不一样的!函数重载是函数名相同但参数列表不同,而运算符重载是我们重新定义运算符的规则和意义。

这里C++给出了一个关键字operator,后面加上运算符,称作函数运算符重载。

然后我们还是通过上面Date d1、d2比较的例子来对此进行说明,例如我们这里将==运算符重载:

operator==(参数1,参数2)  

同时这里还有一件事情值得注意!就是运算符重载的参数列表,是由该运算符的操作数决定的,例如:++只需要一个操作数(所以重载++的参数列表只需要一个参数)、但是<、<<、!=都需要两个操作数(所以这些运算符重载的参数列表需要两个参数)。

所以我们最后以代码形式呈现就是这样:

 bool operator==(Date d1, Date d2)
{return d1._year == d2._year&& d1._month == d2._month&& d1._day == d2._day;
}

但是我们发现:

这是因为Date类中的成员变量都是private私有的,不能被类外访问,当然这个问题很好解决,我们甚至有很多解决方法:

  • 将成员变量改成public公有的(但是这种方法显然不好)
  • 提供函数接口(也就是说,在类中写一个函数,拿到私有的成员变量,然后类外调用函数,太麻烦)
  • 友元(会破坏封装,之后会学到)
  • 将函数放在类中(这个方法是常用的方法)

这里我们先使用第一种方法试试:

#include <iostream>
using namespace std;class Date
{
public:Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}
//我们这里将成员变量改成公有的
//private:int _year;int _month;int _day;
};bool operator==(Date d1, Date d2)
{return d1._year == d2._year&& d1._month == d2._month&& d1._day == d2._day;
}int main()
{Date d1(2025, 8, 6);Date d2(2025, 8, 6);if (d1 == d2){cout << "==" << endl;}return 0;
}

运行结果:

当然是能够成功编译的。

接下来我们重点试一下最后一种方法,将运算符重载放在类中:

但令人奇怪的是,报错了!!!

可是按照逻辑,我们确实应该传入与运算符操作数一样数量的参数,那为什么会报错呢?

原因:

这里其实并不只是两个参数,其实是三个参数。这里我们需要回顾一下我们之前在学习this指针的相关知识,当函数定义在类内部(换句话说一个函数是成员函数)那么就会自带一个this指针。而这里报错的参数过多,就是因为将this统计在内。所以使用最后一种方法,我们只需要传入一个参数,像下面这样:

class Date
{
public:Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}//注意这里的变化!!!bool operator==(Date d){return _year == d._year&& _month == d._month&& _day == d._day;} 
private:int _year;int _month;int _day;
};int main()
{Date d1(2025, 8, 6);Date d2(2025, 8, 6);if (d1 == d2)//编译器会处理成对应重载运算符调用 if (d1.operator(d2)){cout << "==" << endl;}return 0;
}

这时我们编译成功:

然后我们来解释一下这里的调用逻辑:

实际上在使用重载后的==进行比较时,编译器会处理成运算符重载的调用

但是上述我们使用的都是传值传参,都会调用拷贝构造函数。所以我们更好的方法是使用传引用传参,如果不改变的话最后再加上const:

bool operator==(const Date& d)
{return _year == d._year&& _month == d._month&& _day == d._day;
} 

注意:

  • 不能够使用opeartor+其他符号来定义新的运算符,比如:operator@
  • 运算符重载必须要有一个类类型或枚举类型的参数
  • 当运算符重载作为类成员时,参数列表会看起来比运算符操作数少1,这是因为额外传入了this指针
  • 下面5个运算符不能重载(这个经常在笔试选择题中出现):
运算符名称不能重载的原因
::作用域解析运算符必须明确指定类/命名空间,重载会破坏语法结构
.成员访问运算符直接访问对象成员,重载会导致歧义
.*成员指针访问运算符与 . 类似,必须保持原始行为
?:条件运算符(三目)控制流相关,重载可能引发逻辑混乱
sizeof类型/对象大小运算符编译器内置功能,必须返回确定值

大家可以自己实现一下日期>  <  的运算符重载。以及日期+一个天数,日期-日期,日期-天数 的运算符重载(需要考虑显示情况,包含平闰年,大小月等)。下篇文章我尽量更出答案。大家也可以思考尝试写一写~~

(本篇完)

http://www.dtcms.com/a/321926.html

相关文章:

  • 【C#】掌握并发利器:深入理解 .NET 中的 Task.WhenAll
  • Docker容器部署前端Vue服务
  • 复杂路况误报率↓78%!陌讯轻量化模型在车辆违停识别的边缘计算优化​
  • 2025-08-08 李沐深度学习11——深度学习计算
  • 位置编码——RoPE篇
  • 机器学习算法篇(七)深入浅出K-means算法:从原理到实战全解析
  • 【深度学习新浪潮】近三年3DGS在大规模场景重建中的研究进展(2022-2025)
  • 北京上海深圳广州打捞日记
  • 一种基于空间聚类的低特征场景下多目标跟踪技术
  • 什么是ros功能包和ros节点
  • C++程序库选择:权衡与取舍的艺术——以iostream和stdio为例
  • 【大模型】(实践版)Qwen2.5-VL-7B-Instruct模型量化以及运行测试
  • 基于python的农产品销售调度管理的数据可视化系统/基于django的农产品销售系统设计与实现
  • 12-Django项目实战-登录短信验证
  • 解决 MinIO 上传文件时报 S3 API Requests must be made to API port错误
  • 半精度权重 及 Phi-3线性层的权重分布
  • Node.js版本管理,方便好用
  • Mybatis注解开发与事务
  • MPLS LDP标签的分发与管理
  • Linux基础命令速查:从入门到精通
  • 搜广推校招面经一百零三
  • 从手工到智能决策,ERP让制造外贸企业告别“数据孤岛“降本增效
  • Flow的进阶学习2025
  • 亚马逊广告运营如何平衡ASIN投放和关键词投放
  • 用不均匀硬币实现公平决策
  • 虚拟机Ubuntu图形化界面root用户登录错误
  • Python的七大框架对比分析
  • 《嵌入式数据结构笔记(六):二叉树》
  • 【C语言:一个整数分离出每一位数后求重新组合后接近于某个数的整数】
  • STM32传感器模块编程实践(十三)人脸识别模块简介及驱动