【C++】类与对象的学习(中)

目录

一、默认成员函数:

二、构造函数:

1、定义:

2、理解:

三、析构函数:

1、定义:

2、理解:

四、拷贝构造:

1、定义:

2、理解:

五、运算符的重载:

1、一般运算符的重载:

2、赋值运算符的重载:

1、格式:

2、注意:


一、默认成员函数:

一个类中,里面什么都不写的话就叫做空类,但在其中并不是什么都没有的,编译器会自动生成6个默认成员函数。

默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。

二、构造函数:

1、定义:

构造函数是一个特殊的成员函数,它的名字必须和类名相同,创建类类型对象时,由编译器自动调用,,以保证每个数据成员都有 一个合适的初始值,并且在对象整个生命周期内只调用一次。

这是每次创建一个实例时,这个函数都会调用一次。

2、理解:

1、函数名与类名相同。

2、无返回值(也不用写void)。

3、对象实例化的时候,编译器自动调用对应的构造函数。

接下来用一串代码理解上述3条特征。

class Date
{
public:Date(){_year = 2;_month = 2;_day = 2;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};
int main()
{Date d1;d1.Print();return 0;
}

上述代码中,Date()这个就是一个构造函数,和类名相同,也不用写任何返回值,可以看到运行后的结果是已经调用构造函数Date后的值

4、函数构造可以进行重载。

注意:无参构造函数的调用后面不加(),这样和函数的声明会产生歧义。

class Date
{
public:Date(){cout << "无参数构造函数的调用" << endl;_year = 2;_month = 2;_day = 2;}Date(int year, int month, int day){cout << "有三个参数构造函数的调用" << endl;_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};
int main()
{Date d1;//调用无参构造函数d1.Print();Date d2(2024,7,4);//调用带参数的构造函数d2.Print();return 0;
}

5、如果类中没有显式定义构造函数,那么C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。

6、首先要知道:

C++把类型分为了两种:

a、内置类型(基本类型):int/char/double...

b、自定义类型:struct/class/union...

如果我们不写构造函数,那么编译器就会默认生成构造函数,此时这个默认构造函数会对内置类型不做任何处理(虽然有些编译器会进行处理,但那是个性化的,不是所有的编译器都会处理),自定义类型就会去调用它的默认构造。

class Date
{
public:Date(){cout << "无参数构造函数的调用by Date" << endl;_year = 2;_month = 2;_day = 2;}Date(int year, int month, int day){cout << "有三个参数构造函数的调用by Date" << endl;_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};class Stu
{
private:char name[20];int age;char id[15];Date d1;
};int main()
{Stu s1;return 0;
}

如上所示:

实例化Stu这个类,但是发现没有写构造函数,就会默认生成个构造函数,那些内置类型不做处理,自定义类型d1就会调用它的默认构造(Date())。

如下图都是内置类型,就不会做任何处理。

7、无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个

理解:不传参就可以调用的是默认构造函数
注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为
是默认构造函数。

所以:

1、一般情况下,有内置类型成员,就需要自己写构造函数,不能用编译器自己生成。

2、如果全部都是自定义类型的成员,那么就可以考虑使用编译器自己生成的构造函数。

ps:

在C++11中,在成员变量声明的时候可以给缺省值。

如上所示:

在Date这个类中,可以给默认缺省值,给编译器生成默认构造函数用。

注意:

C++11以后才支持的,这里是进行声明(因为没有创建空间),不是初始化!!!

对于构造函数:
一般情况下都需要自己写,

但是,下面两种情况可以不用自己写:

a、内置成员都有缺省值,且初始化符合我们的要求。

b、全是自定义类型的构造,且这些类型都定义默认构造。

三、析构函数:

1、定义:

析构函数与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象销毁时会自动调用析构函数,完成对象中资源的清理工作。

2、理解:

1、析构函数名就是类名前面加上一个“~”;

2、和构造函数一样没有参数返回类型,并且没有参数,所以不能够重载

3、 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数,在程序结束的时候自动调用;

4、自动生成的默认析构函数,对内置类型不做处理,自定义类型会调用其析构函数。

那么什么时候可以显示定义析构函数,什么时候可以不用显示定义析构函数呢:

1、一般,当存在动态申请资源的时候就需要显示定义;

2、当没有动态申请资源的时候就不用显示定义;

3、当需要释放资源的成员变量都是自定义类型的时候,不用写析构,这个自定义类型就会调用它的析构函数。

#include<iostream>
using std::cout;
using std::endl;class Stack
{
public:Stack(){cout << "Stack()已经调用" << endl;_a = (int*)malloc(sizeof(int) * 4);if (_a == nullptr){perror("stack malloc fail");return;}_capacity = 4;_top = 0;}Stack(int capacity){cout << "Stack(int capacity)已经调用" << endl;_a = (int*)malloc(sizeof(int) * capacity);if (_a == nullptr){perror("stack malloc fail");return;}_capacity = capacity;_top = 0;}~Stack(){cout << "~Stack()已经调用" << endl;free(_a);_a = nullptr;_capacity = _top = 0;}
private:int* _a =  nullptr;int _top = 0;int _capacity;
};int main()
{Stack s1;Stack s2(10);return 0;
}

如上~Stack()就是一个析构函数,当对象销毁时就会自动调用。

四、拷贝构造:

首先要了解:C++规定,传参赋值中:创建一个已有对象一模一样的新对象,内置类型直接拷贝,传值的自定义类型必须调用拷贝构造完成拷贝(深浅拷贝有关系)

1、定义:

首先要了解到,拷贝引入是在创建对象的时候,创建一个已有对象一模一样的新对象。

它只有一个形参,该形参是我要复制的对象(一般可以用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。

2、理解:

1、拷贝构造是构造函数的一种重载形式;

2、拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。

3、当没有显示定义拷贝构造函数的时候,默认拷贝构造会对内置类型成员完成值拷贝

                                                                           对自定义类型成员会调用它的拷贝构造

此时在日期类中,可以不用写默认拷贝拷贝构造,正常拷贝,但是有些情况,比如在栈这个类中,如果使用编译器给的默认拷贝构造,会存在问题,会拷贝出同一个指向同一空间的指针,这时如果析构的话,会对同一块空间释放两次,这时程序就会崩溃了。

针对上述为题,我们就需要自己实现拷贝构造,实现深拷贝来解决上述问题。

就要完成开辟一块空间,然后在这块空间里面,拷贝那些值。

class Date
{
public:Date(int year = 2000, int month = 1, int day = 1){_year = year;_month = month;_day = day;}Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}
private:int _year;int _month;int _day;
};int main()
{Date d1(2024, 7, 13);Date d2(d1);return 0;
}

上述就是浅拷贝的例子。

接下来,对这个栈实现深拷贝:

	Stack(Stack& st){_a = (int*)malloc(sizeof(int) * st._capacity);if (_a == nullptr){perror("stack malloc fail");return;}memcpy(_a, st._a, sizeof(int) * st._capacity);_top = st._top;_capacity = st._capacity;}

五、运算符的重载:

1、一般运算符的重载:

C++相对于C语言,增加了运算符重载。使用关键字operator后面加上要重载的运算符。

函数名:operator<

函数原型:返回值类型 operator操作符(参数列表)

注意:

1、不能通过连接其他符号来创建新的操作符:比如operator@(原来没有@这个操作符)
2、重载操作符必须有一个自定义型参数,不能都是内置类型,毕竟是比较自定义类型的,可以自定义类型和内置类型同时存在。    
3、用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不能改变其含义
4、作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
5、    .*    ::     sizeof     ?:     .     注意以上5个运算符不能重载。

bool operator<(const Date& x)
{if (_year > x._year){return false;}else if (_year == x._year && _year > x._year){return false;}else if (_year == x._year && _year > x._year && _day > x._day){return false;}return true;
}

以上就是重载<运算符,_year实际上是this->_year,但是如果写在全局域中,那么就会无法访问私有成员,解决办法可以用友元,或者把operator<写成成员函数。

2、赋值运算符的重载:

1、格式:

1、参数类型:const 类名&,传递引用可以提高传参效率
2、返回值类型:类名&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值
3、返回*this :要复合连续赋值的含义

2、注意:

赋值运算符只能重载成类的成员函数不能重载成全局函数,因为赋值运算符如果不显式实现,编译器会生成一个默认的。此时用户再在类外自己实现一个全局的赋值运算符重载,就和编译器在类中生成的默认赋值运算符重载冲突了,故赋值运算符重载只能是类的成员函数。

在这默认生成赋值重载和拷贝构造行为一样,

对内置类型成员进行值拷贝/浅拷贝,

对自定义类型成员会调用它的赋值重载。

Date& operator=(const Date& d)
{if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return (*this);
}

以上就是在日期类的重载赋值符,这个与拷贝构造不一样,拷贝构造是通过一个类创造一个一样的类,而这个是将一个已经存在的类赋值给另一个已经存在的类。

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

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

相关文章

抖音视频素材是哪里找的?热门的抖音素材网站分享

抖音视频创作高手们&#xff0c;你们是否在寻找下一个爆款视频的完美素材&#xff1f;今天&#xff0c;我将为你们介绍几个优质的视频素材网站&#xff0c;确保你们能在素材的海洋中轻松找到那最耀眼的“珍珠”&#xff01; 蛙学网 首先&#xff0c;我们要推荐的是蛙学网。这个…

Go语言并发编程-同步和锁

同步和锁 概述 同步是并发编程的基本要素之一&#xff0c;我们通过channel可以完成多个goroutine间数据和信号的同步。 除了channel外&#xff0c;我们还可以使用go的官方同步包sync&#xff0c;sync/atomic 完成一些基础的同步功能。主要包含同步数据、锁、原子操作等。 一…

13. C++继承 | 详解 | 虚拟继承及底层实现

目录 1.定义 1.1继承的概念 1.2 继承的定义 2. 对象赋值转换 3. 继承中的作用域 a. 隐藏/重定义 (Hiding/Redefinition) b. 重载 (Overloading) c. 重写/覆盖 (Overriding) d. 编译报错 (Compilation Error) 4. 派生类的默认成员函数 构造 拷贝构造 运算符重载 析…

win11将bat文件固定到“开始“屏幕

一、为bat文件创建快捷方式 (假设bat文件的全名为运行脚本.bat) 右键bat文件&#xff0c;点击显示更多选项 右键菜单选择发送到(N)-桌面快捷方式 二、获取快捷方式的路径 返回桌面&#xff0c;选中创建好的快捷方式&#xff0c;按AltEnter&#xff0c;切换到安全选项卡 鼠…

JCR一区级 | Matlab实现PSO-Transformer-LSTM多变量回归预测

JCR一区级 | Matlab实现PSO-Transformer-LSTM多变量回归预测 目录 JCR一区级 | Matlab实现PSO-Transformer-LSTM多变量回归预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现PSO-Transformer-LSTM多变量回归预测&#xff0c;粒子群优化Transformer结合LST…

Nginx的核心功能

1. Nginx的核心功能 1.1 nginx反向代理功能 正向代理 代理的为客户端&#xff0c;对于服务器不知道真实客户的信息。例如&#xff1a;翻墙软件 反向代理服务器 代理的为服务器端。对于客户来说不知道服务器的信息。例如&#xff1a;nginx 项目部署图 web项目部署的虚拟机和Ng…

鸿蒙语言基础类库:【@system.notification (通知消息)】

通知消息 说明&#xff1a; 从API Version 7 开始&#xff0c;该接口不再维护&#xff0c;推荐使用新接口[ohos.notification]。本模块首批接口从API version 3开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 import notification fro…

httpx 的使用

httpx 是一个可以支持 HTTP/2.0 的库 还有一个是&#xff1a; hyper 库 这里有一个由HTTP/2.0的网站&#xff1a; https://spa16.scrape.center/ 使用 requests 库 进行爬取 import requests url https://spa16.scrape.center/ response requests.get(url) print(response…

达梦数据库的系统视图v$arch_file

达梦数据库的系统视图v$arch_file 在达梦数据库中&#xff0c;V$ARCH_FILE 是一个动态性能视图&#xff0c;用于显示当前数据库的归档日志文件信息。这个视图可以帮助数据库管理员监控和管理归档日志文件&#xff0c;确保数据库的备份和恢复过程顺利进行。 查询本地归档日志信…

Unity UGUI Image Maskable

在Unity的UGUI系统中&#xff0c;Maskable属性用于控制UI元素是否受到父级遮罩组件的影响。以下是关于这个属性的详细说明和如何使用&#xff1a; Maskable属性 Maskable属性&#xff1a; 当你在GameObject上添加一个Image组件&#xff08;比如UI面板或按钮&#xff09;时&…

ctfshow-web入门-php特性(web127-web131)

目录 1、web127 2、web128 3、web129 4、web130 5、web131 1、web127 代码审计&#xff1a; $ctf_show md5($flag); 将 $flag 变量进行 MD5 哈希运算&#xff0c;并将结果赋值给 $ctf_show。 $url $_SERVER[QUERY_STRING]; 获取当前请求的查询字符串&#xff08;que…

开源防病毒工具--ClamAV

产品文档&#xff1a;简介 - ClamAV 文档 开源地址&#xff1a;Cisco-Talos/clamav&#xff1a;ClamAV - 文档在这里&#xff1a;https://docs.clamav.net (github.com) 一、引言 ClamAV&#xff08;Clam AntiVirus&#xff09;是一个开源的防病毒工具&#xff0c;广泛应用…

【算法专题】归并排序

目录 1. 排序数组 2. 交易逆序对的总数 3. 计算右侧小于当前元素的个数 4. 翻转对 总结 1. 排序数组 912. 排序数组 - 力扣&#xff08;LeetCode&#xff09; 今天我们使用归并排序来对数组进行排序&#xff0c;实际上&#xff0c;归并排序和快速排序是有一定相似之处的&a…

Android View的绘制流程

1.不管是View的添加&#xff0c;还是调用View的刷新方法invalidate()或者requestLayout()&#xff0c;绘制都是从ViewRootImpl的scheduleTraversals()方法开始 void scheduleTraversals() {if (!mTraversalScheduled) {mTraversalScheduled true;mTraversalBarrier mHandler…

Linux中nohup(no hang up)不挂起,用于在系统后台不挂断地运行命令,即使退出终端也不会影响程序的运行。

nohup的英文全称是 no hang up&#xff0c;即“不挂起”。这个命令在Linux或Unix系统中非常有用&#xff0c;主要用于在系统后台不挂断地运行命令&#xff0c;即使退出终端也不会影响程序的运行。默认情况下&#xff08;非重定向时&#xff09;&#xff0c;nohup会将输出写入一…

C++之类与对象(1)

目录 前言 1.类的定义 1.1类定义的格式 1.2访问限定符 1.3类域 1.3.1类定义一个作用域 1.3.2类成员在类的作用域中 1.3.3在类体外定义成员 2.实例化 2.1实例化概念 2.2对象大小 3.this指针 4.选择题补充练习 结束语 前言 Hello&#xff0c;友友们&#xff0c;好久…

Linux安装mysql(超详细版)

步骤1&#xff1a;新建一个文件夹&#xff0c;专放从网络下载的文件 [rootiZ2zeh6vyxsq620zifz8jaZ home]#mkdir soft #在根目录下创建也可以 步骤2&#xff1a;切换目录&#xff0c;进入soft文件中 [rootiZ2zeh6vyxsq620zifz8jaZ /]# cd home/ #若第一步文件建在根目…

牛客周赛 Round 51

目录 A.小红的同余 B.小红的三倍数 C.小红充电 D.小红的gcd E.小红走矩阵 F.小红的数组 这次周赛题目比较简单&#xff0c;算法题也基本上是板子题&#xff0c;出得很好(&#xff5e;&#xffe3;▽&#xffe3;)&#xff5e; A.小红的同余 思路&#xff1a;签到题&am…

Android Studio 不再支持windows 7

Android Studio 一打开就报错&#xff1a; 无法找到入口 无法定位程序输入点 CreateAppContainerProfle 于动态链接库USERENV.dII 上。 截图如下&#xff1a; 经调查&#xff0c;是因为系统版本不兼容。 我目前的电脑环境&#xff1a;windows 7,但是现在的Android Studio要…

24年Hvv准备,6大方向,33篇技战法

进去不少小伙伴后台留言说需要技战法&#xff0c;因此小编对市面上的技战法进行了收集和总结&#xff0c;并对收集来的技战法进行了分类&#xff0c;总共分了6大类&#xff0c;共计33篇&#xff1a; 有需要的小伙伴关注我&#xff0c;点击在看&#xff0c;并私信回复“技战法”…