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

C++类和对象基础笔记总结(默认成员函数)

上篇文章我总结到了析构函数,接下来我们来看看剩下的两个函数:

1.拷贝构造函数

如果一个构造函数的第一个参数是自身类类型的引用,且任何额外的参数都有默认值,则此构造函数也可叫做拷贝构造函数,也就是说拷贝构造函数就是一个特殊的构造函数。

拷贝构造的特点

  1. 拷贝构造函数是构造函数的一个重载。
  2. C++规定自定义类型对象进行拷贝行为必须调用拷贝构造,所以自定义类型传值传参和传值返回都会调用拷贝构造完成。
  3. 拷贝构造函数的参数第一个参数必须是类类型对象的引用,使用传值方式编译器会直接报错,因为语法上会引发无穷递归。
  4. 若未显示定义拷贝构造函数,编译器会自动生成拷贝构造函数。自动生成的拷贝构造对内置成员变量会完成浅拷贝(一个字节一个字节的拷贝),对自定义类型成员变量会调用其的拷贝构造。

我们来看下面的代码:

我们创建了一个日期类的date类,第一个函数是他的构造函数,第二个则是他的拷贝构造函数,那么这两个函数有何区别呢?我们来看下方的代码:

int main()
{//date d1();  错误写法,可能是函数声明date d1;date d2 = d1;//date d2(d1);d1.print();d2.print();return 0;
}

首先我们在实例化对象时,不能写date d1();这种,因为编译器不清楚这是否是函数声明。后两行代码分别创建了d1,d2对象,他们两个创建的方法是不一样的,d1去调用第一个构造函数,d2去调用拷贝构造函数,而我们函数实现功能就是创建一个和d1值一样的d2。写成date d2(d1)和date d2 = d1是一样的,编译器都会去调用拷贝构造。

那么对于一个只有内置类型的日期类date,如果我们不写拷贝构造函数,那么像上方代码还能完成date d2 = d1 操作吗?答案是可以的,因为我们在拷贝构造函数特点第四点已经讲到。那么拷贝函数到底有什么用呢?

class Stack
{
public:Stack():_a((int*)malloc(sizeof(int)*10)),_top(0),_capacity(10){if (_a == nullptr){perror("malloc fail");return;}}~Stack(){free(_a);_a = nullptr;_top = _capacity = 0;}
private:int* _a;int _top;int _capacity;
};

我们来看上面的代码,这是一个Stack类的栈,如果我们简单的在main函数里面完成下面的操作:

Stack st1;  Stack st2 = st1;,那么我们的程序就会报错,因为对于Stack类,在私有成员中有一个int* _a的成员,我们在初始化列表时已经初始化_a,如果我们不写拷贝构造函数,因为是浅拷贝,那么st2中的_a将与st1中的_a,是同一块地址,调用析构函数时,就会析构两遍,我们不可能将同一块地址free两次,因此就会报错。

因此我们对于一个类,显示实现了析构并释放了资源,我们就需要写拷贝构造函数:

​
class Stack
{
public:Stack():_a((int*)malloc(sizeof(int)*10)),_top(0),_capacity(10){if (_a == nullptr){perror("malloc fail");return;}}Stack(const Stack& s):_a((int*)malloc(sizeof(int) * s._capacity)),_top(s._top),_capacity(s._capacity){for (int i = 0; i < _top; i++){_a[i] = s._a[i];}}~Stack(){free(_a);_a = nullptr;_top = _capacity = 0;}
private:int* _a;int _top;int _capacity;
};​

2.运算符重载

我们都知道如果我们定义两个int类型,我们可以比较他们是否相等,或者比较出哪一个int比较大,我们也可以进行加减乘除运算等。那么我们实现了日期类date能否像int那样呢?答案是可以的,C++支持我们使用运算符重载来完成这件事。

bool date::operator<(const Date& d)const
{if (_year < d._year){return true;}else if (_year == d._year){if (_month < d._month){return true;}else if (_month == d._month){if (_day < d._day){return true;}}}return false;
}

这是一个简单的<运算符重载,类似于一个函数,只不过这个函数名为operator并且在名后面加上需要重载的运算符即可,其他的地方与函数基本一致。这样我们就可以比较两个日期类的大小了。

运算符重载的特点

  1. 运算符重载函数的参数个数和该运算符作用的运算对象数量一样多。一元运算符有一个参数,二元运算符有两个参数,二元运算符的左侧运算对象传给第一个参数。右侧运算对象传给第二个参数。
  2. 如果一个重载运算符是成员函数,则它的第一个运算对象默认传给隐式的this指针,因此运算符重载作为成员函数时,参数比运算对象少一个。
  3. 运算符重载以后,其优先级和结合性与对应的内置类型运算符保持一致。
  4. 不能通过连接语法中没有的符号来创建新的操作符:例如operator@。
  5. 重载++运算符时,有前置++(--)和后置++(--),运算符重载函数名都是operator++,无法很好的区分。因此C++规定,后置++(--)重载时,增加一个int形参,与前置++构成重载函数,以便区分。

以上内容如有错误欢迎批评指正!!

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Apache Doris:下一代实时数据仓库
  • 阿里云Linux中安装MySQL,并使用navicat连接以及报错解决
  • EasyCVR视频技术:城市电力抢险的“千里眼”,助力抢险可视化
  • SpinalHDL之VHDL 和 Verilog 生成
  • 【2024_CUMCM】时间序列1
  • 【TOOLS】Chrome扩展开发
  • struts2如何防止XSS脚本攻击(XSS防跨站脚本攻击过滤器)
  • CentOS7配置阿里云yum源
  • WPF学习(2) -- 样式基础
  • spark运行报错:Container killed by YARN for exceeding memory limits
  • Vue 3 组件通信全解:从基础到高级技巧
  • Redis② —— Redis线程模型
  • <数据集>绝缘子缺陷检测数据集<目标检测>
  • 昇思25天学习打卡营第20天|CycleGAN图像风格迁移互换
  • MVC 返回集合方法,以及分页
  • echarts花样作死的坑
  • java8-模拟hadoop
  • java多线程
  • k8s 面向应用开发者的基础命令
  • laravel5.5 视图共享数据
  • Lucene解析 - 基本概念
  • PaddlePaddle-GitHub的正确打开姿势
  • Redis学习笔记 - pipline(流水线、管道)
  • STAR法则
  • 百度贴吧爬虫node+vue baidu_tieba_crawler
  • 从零开始学习部署
  • 短视频宝贝=慢?阿里巴巴工程师这样秒开短视频
  • 分布式任务队列Celery
  • 给Prometheus造假数据的方法
  • 力扣(LeetCode)22
  • 爬虫进阶 -- 神级程序员:让你的爬虫就像人类的用户行为!
  • 前端设计模式
  • 限制Java线程池运行线程以及等待线程数量的策略
  • 正则表达式
  • 字符串匹配基础上
  • 最近的计划
  • gunicorn工作原理
  • ​​​​​​​​​​​​​​Γ函数
  • ​html.parser --- 简单的 HTML 和 XHTML 解析器​
  • ​埃文科技受邀出席2024 “数据要素×”生态大会​
  • ​卜东波研究员:高观点下的少儿计算思维
  • # MySQL server 层和存储引擎层是怎么交互数据的?
  • #QT(TCP网络编程-服务端)
  • $.each()与$(selector).each()
  • (2/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (a /b)*c的值
  • (done) NLP “bag-of-words“ 方法 (带有二元分类和多元分类两个例子)词袋模型、BoW
  • (Redis使用系列) Springboot 实现Redis 同数据源动态切换db 八
  • (附源码)计算机毕业设计SSM在线影视购票系统
  • (六)vue-router+UI组件库
  • (论文阅读23/100)Hierarchical Convolutional Features for Visual Tracking
  • (十二)devops持续集成开发——jenkins的全局工具配置之sonar qube环境安装及配置
  • (一)Neo4j下载安装以及初次使用
  • (转)PlayerPrefs在Windows下存到哪里去了?
  • (转)树状数组