C++ 类和对象 (中)

默认成员函数:

C++环境下每一个类在定义是时编译器会自动生成六个成员函数(在没有显示定义的情况下),分别是构造函数、析构函数、拷贝构造函数、赋值运算符重载、普通变量和const常量的取地址重载,它们大大弥补了原先C语言的一些不足,为代码编写者提供了极大的遍历,下面我们来一一解释各个默认成员函数

构造函数:

以栈数据结构为例子,C环境下我们在实例化一个栈结构的时候,必须手动调用初始化函数,但这一步也经常在编写代码的时候忽略,本贾尼先生思来想去想出了一个绝妙的方法,即在实例化类对象的同时让编译器自动调用一个能够给类属性赋初值的成员函数
为了区分与一般成员函数的与众不同,构造函数的形式非常独特,它没有返回值,但不需要再声明定义处前加上void关键字,当不需要传参时调用不需要添加空括号,函数名与类对象名相同。

//栈
class Stack
{
public:Stack(int n=4){_a=(int*)malloc(sizeof(int)*n);_size=0;_capacity=0;}   //显示定义带有缺省值构造函数
private:int *_a;int _size;int _capacity;
};Stack st1;  //不传参调用,写括号编译器分不清是调用还是声明
Stack st1(10);  //传参调用

如果我们显示声明定义了构造函数,那么编译器就不会自动生成,而是执行我们写的,那么如果我们不写的话打印一下三个类属性会出现什么结果呢?
答案是一串随机值,这里可以说是C++的一个缺陷,自动生成的构造函数不会对内置类型作出任何处理,只对自定义类型调用该类型本身的构造函数,举个例子

class Queue
{
public:Queue(){_head=_tail=nullptr;}
private:int* _head;int * _tail;
};
//定义一个Queue对象 q1 充当Stack的类属性

在调试窗口观察四个类属性的值,
在这里插入图片描述
q的值确实被初始化成了空指针(由于编译器版本的原因,可能会将内置类型初始化为0,但这里我们依然认为不对内置类型做处理

C++11在此基础上做了优化,在类属性声明处可以直接给缺省值来实现初始化,具体例子在讲解拷贝构造时给出

析构函数:

C环境下总是要手动调用销毁结构释放空间,同样极易被遗忘,从而在C++环境中衍生出另一个默认成员函数,当类对象生命结束时会自动调用析构函数实现空间释放
与构造函数很像,析构函数也是没有返回值且不需要前缀void的特殊函数,并且它不具有参数,不能重载(构造函数可以重载
为了区分构造函数,析构函数的函数名前有前缀按位取反符 ~

//实现一个栈的析构函数
class Stack{
public://………………~Stack(){free(_a);_a=nullptr;_size=_capacity=0;}//………………
};

同理如果不显示声明定义,编译器会自动生成析构函数并调用

拷贝构造函数:

我们有时候会想要创造一个与一个已有类对象的对象,这个时候我们就需要拷贝,编译器默认的拷贝方式是浅拷贝(值拷贝),即将被拷贝的值逐个字节的传递给拷贝值,这样的方式对于int、char、double这些内置类型是没有问题的,但是对于指针类型或者自定义类型是不行的,原因是因为如果含有指针类型,浅拷贝后会出现两个指针指向同一块空间的情况,这样出现两次析构的时候就会报错,因此这里需要采用深拷贝的方式,C++使用了拷贝构造函数来实现。

拷贝构造函数是构造函数的重载,没有返回值,参数类对象引用,(这里必须通过引用传参,一是能够提升效率,二是如果传值调用会出现无限递归的结果导致程序崩溃,具体图解在后文会给出

class Date//定义日期类
{
public:Date(const Date& d){    //我们不想改变被拷贝值,加const是一个好习惯_year=d._year;_month=d._month;_day=d._day;}
private:_year=2024;_month=1;_day=1;//C++11的特性
};Date d1;
Date d2(d1);//①
Date d2=d1; //②   两种方法是等价的,都是初始化时将d1值拷贝给d2

解释为何不能传值调用:
既定事实:自定义类型的拷贝需要使用拷贝构造
在这里插入图片描述

运算符重载:

C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。

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

1、不能通过连接其他符号来创建新的操作符:比如operator@
2、重载操作符必须有一个类类型或者枚举类型的操作数
3、用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不 能改变其含义
4、作为类成员的重载函数时,其形参看起来比操作数数目少1成员函数的操作符有一个默认的形参this,限定为第一个形参
5、**.
、:: 、sizeof 、?: 、.** 注意以上5个运算符不能重载*

以对+运算符的重载为例(Date类)

class Date//定义日期类
{
public:Date& operator+(int year) {_year+=year;return *this;//思考一下为什么传引用返回}
private:_year=2024;_month=1;_day=1;//C++11的特性
};Date d1;
d1+1;//隐式调用
d1.operator+(1);//显示调用

赋值运算符重载:
赋值运算符作为默认成员函数之一,对于类属性只有内置类型的对象可以不需要我们手动编写,编译器会自动生成并调用。

取地址重载:

class Date
{ 
public :Date* operator&(){return this ;}const Date* operator&(){return this ;}
private :int _year ;  int _month ;  int _day ; 
};

这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,故不做过多阐述。

……………………………………………………………………………………………………

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/314208.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【进阶KMP算法】nextval手算代码均有详解(每步配图)

这里是进阶,所以如果有小伙伴不知道KMP算法是什么的话,请看上一章(写的很清楚),故我这里概念什么的就不再过多描述。 引入: 要改进那么肯定要知道,哪里有不足,我们假设目标串s为“…

c# 捕获全部线程的异常 试验

1.概要 捕获全部线程的异常 试验,最终结果task的异常没有找到捕获方法 2.代码 2.1.试验1 2.1.1 试验结果 2.2 代码 2.2.1主程序代码 using NLog; using System; using System.Threading; using System.Windows.Forms;namespace 异常监控 {static class Program…

C++继承与派生——(8)多继承

归纳编程学习的感悟, 记录奋斗路上的点滴, 希望能帮到一样刻苦的你! 如有不足欢迎指正! 共同学习交流! 🌎欢迎各位→点赞 👍 收藏⭐ 留言​📝 苦难和幸福一样,都是生命盛…

Java API 操作Docker浅谈

背景: 使用com.github.docker-java库可以很方便地在Java中操作Docker。下面是一个详细的教程,包括创建镜像、创建容器、启动容器、停止容器和删除容器的步骤以及每一步的说明。 前提: 首先,在你的Java项目中添加com.github.doc…

gRPC之内置Trace

1、内置Trace grpc内置了客户端和服务端的请求追踪,基于golang.org/x/net/trace包实现,默认是开启状态,可以查看事 件和请求日志,对于基本的请求状态查看调试也是很有帮助的,客户端与服务端基本一致,这里…

c++写入数据到文件中

假设你想编写一个C程序&#xff1a;当你在调试控制台输入一些数据时&#xff0c;系统会自动存入到指定的文件中&#xff0c;该如何操作呢&#xff1f; 具体操作代码如下&#xff1a; #include<iostream> #include<string> #include<fstream> using namespa…

服务器硬件及RAID配置实战

目录 1、RAID的概念 2、RAID的实现方式 3、标准的RAID 3.1 RAID 0 3.2 RAID 1 3.3 RAID 5 3.4 RAID 10 4、建立硬件 RAID的过程步骤 1、进入RAID 1.1 重启服务器 1.2 进入RAID界面 1.3 在RAID界面切换目录 2、创建RAID 2.1 移动到RAID卡 2.2 按F2&#xff0c;选择…

AspectJWeaver之Gadget分析

前言&#xff1a; 今天看了下ysoserial的AspectJWeaver方法&#xff0c;分析了下其是如何通过调用SimpleCache$StorableCachingMap来实现写文件&#xff0c;这里把分析的流程写下来&#xff1a; 首先我们要看下其所需要的jar包&#xff1a; <dependencies><dependen…

redis 从0到1完整学习 (十二):RedisObject 之 List 类型

文章目录 1. 引言2. redis 源码下载3. redisObject 管理 List 类型的数据结构3.1 redisObject 管理 List 类型3.2 List PUSH 源码 4. 参考 1. 引言 前情提要&#xff1a; 《redis 从0到1完整学习 &#xff08;一&#xff09;&#xff1a;安装&初识 redis》 《redis 从0到1…

SQL性能优化-索引

1.性能下降sql慢执行时间长等待时间长常见原因 1&#xff09;索引失效 索引分为单索、复合索引。 四种创建索引方式 create index index_name on user (name); create index index_name_2 on user(id,name,email); 2&#xff09;查询语句较烂 3&#xff09;关联查询太多join&a…

边缘计算网关在温室大棚智能控制系统应用,开启农业新篇章

项目需求 ●目前大棚主要通过人为手动控温度、控水、控光照、控风&#xff0c;希望通过物联网技术在保障产量的前提下&#xff0c;提高作业效率&#xff0c;降低大棚总和管理成本。 ●释放部分劳动力&#xff0c;让农户有精力管理更多大棚&#xff0c;进而增加农户收入。 ●…

WEB 3D技术 three.js通过光线投射 完成几何体与外界的事件交互

本文 我们来说 光线投射 光线投射技术是用于3维空间场景中的交互事件 我们先编写代码如下 import ./style.css import * as THREE from "three"; import { OrbitControls } from "three/examples/jsm/controls/OrbitControls.js";const scene new THRE…