C++——类与对象(中)

目录

  1. 类的6个默认成员函数
  2. 构造函数
  3. 析构函数
  4. 拷贝构造函数
  5. 赋值运算符重载
  6. const成员函数
  7. 取地址及const取地址操作符重载

1.类的6个默认成员函数

如果一个类中什么成员都没有,简称为空类。
空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。
默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。

class Date {};

在这里插入图片描述

2. 构造函数

2.1概念

class Date
{
public:void Init(int year, int month, int day){_year = year;_month = month;_day = day;}
private:int _year;  // year_  mYearint _month;int _day;
};

对于Date类,可以通过 Init 公有方法给对象设置日期,但如果每次创建对象时都调用该方法设置信息,未免有点麻烦,那能否在对象创建时,就将信息设置进去呢?
构造函数是一个特殊的成员函数,名字与类名相同,创建类类型对象时由编译器自动调用,以保证每个数据成员都有 一个合适的初始值,并且在对象整个生命周期内只调用一次。

2.2 特性

构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象,而是初始化对象。
其特征如下:

  1. 函数名与类名相同。
  2. 无返回值。
  3. 对象实例化时编译器自动调用对应的构造函数。
  4. 构造函数可以重载
class Date
{public:// 1.无参构造函数Date(){}// 2.带参构造函数Date(int year, int month, int day){_year = year;_month = month;_day = day;}private:int _year;int _month;int _day;
};void TestDate()
{Date d1; // 调用无参构造函数Date d2(2023, 8, 2); // 调用带参的构造函数// 注意:如果通过无参构造函数创建对象时,对象后面不用跟括号,否则就成了函数声明// 以下代码的函数:声明了d3函数,该函数无参,返回一个日期类型的对象// warning C4930: “Date d3(void)”: 未调用原型函数(是否是有意用变量定义的?)Date d3();
}
  1. 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。
class Date
{public:
/*
// 如果用户显式定义了构造函数,编译器将不再生成
Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
}
*/
void Print()
{
cout << _year << "-" << _month << "-" << _day << endl;
}private:
int _year;
int _month;
int _day;
};int main()
{
// 将Date类中构造函数屏蔽后,代码可以通过编译,因为编译器生成了一个无参的默认构造函// 将Date类中构造函数放开,代码编译失败,因为一旦显式定义任何构造函数,编译器将不再
生成// 无参构造函数,放开后报错:error C2512: “Date”: 没有合适的默认构造函数可用
Date d1;
return 0;
}
  1. 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。
    注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数。

3.析构函数

3.1概念

通过前面构造函数的学习,我们知道一个对象是怎么来的,那一个对象又是怎么没呢的?
析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。

3.2特性

析构函数是特殊的成员函数,其特征如下:

  1. 析构函数名是在类名前加上字符 ~。
  2. 无参数无返回值类型。
  3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载
  4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。

4. 拷贝构造函数

概念
在创建对象时,可否创建一个与已存在对象一某一样的新对象呢?
拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。

特征

拷贝构造函数也是特殊的成员函数,其特征如下:

  1. 拷贝构造函数是构造函数的一个重载形式。
  2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错,因为会引发无穷递归调用。
  3. 若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。
  4. 拷贝构造函数典型调用场景:
    使用已存在对象创建新对象
    函数参数类型为类类型对象
    函数返回值类型为类类型对象

5.赋值运算符重载

C++为了增强代码的可读性引入了运算符重载,运算符重载是具有特殊函数名的函数,也具有其返回值类型,函数名字以及参数列表,其返回值类型与参数列表与普通的函数类似。
函数名字为:关键字operator后面接需要重载的运算符符号。
函数原型:返回值类型 operator操作符(参数列表)
注意:
不能通过连接其他符号来创建新的操作符:比如operator@
重载操作符必须有一个类类型参数用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this。

#define _CRT_SECURE_NO_WARNINGS 1#define _CRT_SECURE_NO_WARNINGS 1#include <iostream>using namespace std;
class Date
{public:// 获取某年某月的天数int GetMonthDay(int year, int month){int Month[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };if (month == 2 && (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)){return 29;}return Month[month];}// 全缺省的构造函数Date(int year = 1900, int month = 1, int day = 1){_year = year;_month = month;_day = day;}// 拷贝构造函数// d2(d1)Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}// 赋值运算符重载// d2 = d3 -> d2.operator=(&d2, d3)Date& operator=(const Date& d){this->_year = d._year;this->_month = d._month;this->_day = d._day;return *this;}// 析构函数~Date(){}// 日期+=天数Date& operator+=(int day){this->_day += day;while (this->_day > GetMonthDay(this->_year, this->_month)){this->_day -= GetMonthDay(this->_year, this->_month);this->_month++;if (this->_month == 13){this->_year++;this->_month = 1;}}return *this;}// 日期+天数Date operator+(int day){*this += day;Date tmp(*this);return tmp;}// 日期-天数Date operator-(int day){Date tmp(*this);tmp -= day;return tmp;}// 日期-=天数Date& operator-=(int day){if (day < this->_day){this->_day -= day;}else{while (day >= this->_day){if (this->_month == 1){this->_year--;this->_month = 13;}this->_month--;this->_day += GetMonthDay(this->_year, this->_month);}this->_day -= day;}return *this;}// 前置++Date& operator++(){this->_day++;if (this->_day > GetMonthDay(this->_year, this->_month)){this->_day -= GetMonthDay(this->_year, this->_month);this->_month++;if (this->_month == 13){this->_year++;this->_month = 1;}}return *this;}// 后置++Date operator++(int){Date tmp(*this);++tmp._day;if (tmp._day > GetMonthDay(tmp._year, tmp._month)){tmp._day -= GetMonthDay(tmp._year, tmp._month);tmp._month++;if (tmp._month == 13){tmp._year++;tmp._month = 1;}}return tmp;}// 后置--Date operator--(int){Date tmp(*this);if (this->_day > 1){this->_day--;}else{if (this->_month == 1){this->_year--;this->_month = 13;}this->_month--;this->_day = this->_day + GetMonthDay(this->_year, this->_month) - 1;}return tmp;}// 前置--Date& operator--(){if (this->_day > 1){this->_day--;}else{if (this->_month == 1){this->_year--;this->_month = 13;}this->_month--;this->_day = this->_day + GetMonthDay(this->_year, this->_month) - 1;}return *this;}// >运算符重载bool operator>(const Date& d){if (this->_year > d._year){return true;}else if (this->_year == d._year && this->_month > d._month){return true;}else if (this->_year == d._year && this->_month == d._month && this->_year > d._year){return true;}else{return false;}}// ==运算符重载bool operator==(const Date& d){return this->_year == d._year &&this->_month == d._month &&this->_day == d._day;}// >=运算符重载bool operator >= (const Date& d){return (*this > d || *this == d);}// <运算符重载bool operator < (const Date& d){if (this->_year < d._year){return true;}else if (this->_year == d._year && this->_month < d._month){return true;}else if (this->_year == d._year && this->_month == d._month && this->_year < d._year){return true;}else{return false;}}// <=运算符重载bool operator <= (const Date& d){return (*this < d || *this == d);}// !=运算符重载bool operator != (const Date& d){return !(*this == d);}// 日期-日期 返回天数//日期相减  相差天数int operator-(const Date& d){//小日期经过多少次自加与大日期相同Date max = *this;Date min = d;int flag = 1;if (max < min){max = d;min = *this;flag = -1;}int day = 0;while (min < max){++min;++day;}return flag * day;}int getyear(){return this->_year;}int getmonth(){return this->_month;}int getday(){return this->_day;}private:int _year;int _month;int _day;};int main()
{Date date2(1970, 1, 1);Date date1(2023, 7, 22);cout << "当前日期为:" << date1.getyear() << "-" << date1.getmonth() << "-" << date1.getday() << endl;date1 += 1;cout << "当前日期后1天为:" << date1.getyear() << "-" << date1.getmonth() << "-" << date1.getday() << endl;date1 += 30;cout << "当前日期后30天为:" << date1.getyear() << "-" << date1.getmonth() << "-" << date1.getday() << endl;date1 += 90;cout << "当前日期后90天为:" << date1.getyear() << "-" << date1.getmonth() << "-" << date1.getday() << endl;date1 += 360;cout << "当前日期后360天为:" << date1.getyear() << "-" << date1.getmonth() << "-" << date1.getday() << endl;cout << "当前日期为:" << date2.getyear() << "-" << date2.getmonth() << "-" << date2.getday() << endl;date2 += 1;cout << "当前日期后1天为:" << date2.getyear() << "-" << date2.getmonth() << "-" << date2.getday() << endl;date2 += 30;cout << "当前日期后30天为:" << date2.getyear() << "-" << date2.getmonth() << "-" << date2.getday() << endl;date2 += 90;cout << "当前日期后90天为:" << date2.getyear() << "-" << date2.getmonth() << "-" << date2.getday() << endl;date2 += 360;cout << "当前日期后360天为:" << date2.getyear() << "-" << date2.getmonth() << "-" << date2.getday() << endl;cout << "date1 - date2: " << (date1 - date2) << "天" << endl;cout << "date1 < date2: " << (date1 < date2) << endl;cout << "date1 <= date2: " << (date1 <= date2) << endl;cout << "date1 == date2: " << (date1 == date2) << endl;cout << "date1 > date2: " << (date1 > date2) << endl;cout << "date1 >= date2: " << (date1 >= date2) << endl;(date1++);cout << "date1++ :" << date1.getyear() << "-" << date1.getmonth() << "-" << date1.getday() << endl;date1--;cout << "date1-- :" << date1.getyear() << "-" << date1.getmonth() << "-" << date1.getday() << endl;--date1;cout << "--date1 :" << date1.getyear() << "-" << date1.getmonth() << "-" << date1.getday() << endl;++date1;cout << "++date1 :" << date1.getyear() << "-" << date1.getmonth() << "-" << date1.getday() << endl;}

运行结果截图:
在这里插入图片描述

6.const成员

将const修饰的“成员函数”称之为const成员函数,const修饰类成员函数,实际修饰该成员函数隐含的this指针,表明在该成员函数中不能对类的任何成员进行修改。

在这里插入图片描述

8.取地址及const取地址操作符重载

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

这两个运算符一般不需要重载,使用编译器生成的默认取地址的重载即可,只有特殊情况,才需要重载,比如想让别人获取到指定的内容!

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

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

相关文章

TCP三次握手与四次断开

TCP三次握手机制 三次握手是指建立一个TCP连接时&#xff0c;需要客户端和服务器总共发送3个包。进行三次握手的主要作用就是为了确认双方的接收能力和发送能力是否正常、指定自己的初始化序列号为后面的可靠性传送做准备。 1、客户端发送建立TCP连接的请求报文&#xff0c;其…

物理分代垃圾回收器

内存结构 内存分配 堆上分配 大多数情况在eden【年轻代中的一个区域】上分配&#xff0c;偶尔会直接在old【老年代】上分配&#xff0c;细节取决于GC的实现。栈上分配&#xff08;发生了指针逃逸&#xff0c;又叫指针逃逸分析——JVM优化&#xff09; 原子类型的局部变量。 G…

eclipse 最新版没有navigator视图如何解决

使用project exploere视图可以显示类似navigator视图 1.显示project exploere视图 window---->show view --->project exploere 2.project exploere视图转换为类似navigator视图 第一步&#xff1a;点击视图右上角三个点或者倒三角&#xff0c;点击fiters and custom…

3DEXPERIENCE用户角色 | Structural Mechanics Engineer 结构力学工程师

真实条件下实施复杂的线性和非线性分析 直观验证设计并更快地做出产品决策 Structural Mechanics Engineer 在基于云的 3DEXPERIENCE 平台上构建&#xff0c;您可对产品行为执行结构线性和非线性静态、低速和高速动态和热仿真。具备材料校准功能&#xff0c;有助于确保材料行为…

Python教程(6)——Python变量的基础类型。|整数类型|浮点数类型|字符串类型|布尔类型|

学习编程语言&#xff0c;不得不忽视变量这个概念。Python 中的变量是用于存储数据的名称&#xff0c;你可以将值赋给变量&#xff0c;并在程序的其他地方使用该变量来引用该值。变量在程序中起到存储和操作数据的作用。 如果学过C/C语言的同学&#xff0c;定义了变量后&#…

无涯教程-Lua - repeat...until 语句函数

与 for 和 while 循环(它们在循环顶部测试循环条件)不同&#xff0c;Lua编程中的 repeat ... until 循环语言在循环的底部检查其条件。 repeat ... until 循环与while循环相似&#xff0c;不同之处在于&#xff0c;保证do ... while循环至少执行一次。 repeat...until loop - …

单机,集群和分布式概念

单机的局限性&#xff1a; 1.受限于硬件资源&#xff0c;单机所能承受的用户并发量太少&#xff1b; 2.一个系统有多个模块&#xff0c;任意模块的修改都会导致整个项目代码重新编译、部署&#xff1b; 3.系统中&#xff0c;有些模块是CPU密集型&#xff0c;有些模块是I/O密…

通过案例实战详解elasticsearch自定义打分function_score的使用

前言 elasticsearch给我们提供了很强大的搜索功能&#xff0c;但是有时候仅仅只用相关度打分是不够的&#xff0c;所以elasticsearch给我们提供了自定义打分函数function_score&#xff0c;本文结合简单案例详解function_score的使用方法&#xff0c;关于function-score-query…

InnoDB引擎底层逻辑讲解——架构之内存架构

1.InnoDB引擎架构 下图为InnoDB架构图&#xff0c;左侧为内存结构&#xff0c;右侧为磁盘结构。 2.InnoDB内存架构讲解 2.1 Buffer Pool缓冲池 2.2 Change Buffer更改缓冲区 2.3 Adaptive Hash Index自适应hash索引 查看自适应hash索引是否开启&#xff1a; show variable…

6.s081(Fall 2022)Lab2: system calls

文章目录 前言其他篇章参考链接0. 前置准备1. System call tracing (moderate)简单分析Hint 1Hint 2Hint 3Hint 4Hint 5测试 2. Sysinfo (moderate) 前言 好像没啥前言 其他篇章 环境搭建 Lab1:Utilities 参考链接 官网链接 xv6手册链接&#xff0c;这个挺重要的&#xff…

Spring Data Elasticsearch - 在Spring应用中操作Elasticsearch数据库

Spring Data Elasticsearch 文章目录 Spring Data Elasticsearch1. 定义文档映射实体类2. Repository3. ElasticsearchRestTemplate3.1 查询相关特性3.1.1 过滤3.1.2 排序3.1.3 自定义分词器 3.2 高级查询 4. 索引管理4.1 创建索引4.2 检索索引4.3 修改映射4.4 删除索引 5. 异常…

GO学习之 多线程(goroutine)

GO系列 1、GO学习之Hello World 2、GO学习之入门语法 3、GO学习之切片操作 4、GO学习之 Map 操作 5、GO学习之 结构体 操作 6、GO学习之 通道(Channel) 7、GO学习之 多线程(goroutine) 文章目录 GO系列前言一、并发介绍1.1 进程和线程和协程1.2 并发和并行 二、goroutine介绍三…

AWS——02篇(AWS之服务存储EFS在Amazon EC2上的挂载——针对EC2进行托管文件存储)

AWS——02篇&#xff08;AWS之服务存储EFS在Amazon EC2上的挂载——针对EC2进行托管文件存储&#xff09; 1. 前言2. 关于Amazon EFS2.1 Amazon EFS全称2.2 什么是Amazon EFS2.3 优点和功能2.4 参考官网 3. 创建文件系统3.1 创建 EC2 实例3.2 创建文件系统 4. 在Linux实例上挂载…

服务器硬件、部署LNMP动态网站、部署wordpress、配置web与数据库服务分离、配置额外的web服务器

day01 day01项目实战目标单机安装基于LNMP结构的WordPress网站基本环境准备配置nginx配置数据库服务部署wordpressweb与数据库服务分离准备数据库服务器迁移数据库配置额外的web服务器 项目实战目标 主机名IP地址client01192.168.88.10/24web1192.168.88.11/24web2192.168.88…

『赠书活动 | 第十三期』《算力经济:从超级计算到云计算》

&#x1f497;wei_shuo的个人主页 &#x1f4ab;wei_shuo的学习社区 &#x1f310;Hello World &#xff01; 『赠书活动 &#xff5c; 第十三期』 本期书籍&#xff1a;《算力经济&#xff1a;从超级计算到云计算》 赠书规则&#xff1a;评论区&#xff1a;点赞&#xff5c;收…

线段树合并例题

https://www.luogu.com.cn/problem/P3224 1. 永无乡 题意&#xff1a; 给 n 个岛屿&#xff0c;每个岛有一个标号&#xff0c;初始修有 m 条路&#xff0c;有两个操作&#xff0c;操作1 为 给两个岛屿之间修路&#xff0c;操作2为求出 所有能从当前岛屿到达的岛 中标号第k小的…

前端需要知道的计算机网络知识

1 Web 机制 无论通过有线方式 (通常是网线) 还是无线方式&#xff08;比如 wifi 或蓝牙)&#xff0c;通信需要进行连接&#xff0c;网络上的每台计算机需要链接到路由器&#xff08;router&#xff09;。 路由器确保从一台计算机上发出的一条信息可以到达正确的计算机。计算机…

【Android Framework系列】第9章 AMS之Hook实现登录页跳转

1 前言 前面章节我们学习了【Android Framework系列】第5章 AMS启动流程和【Android Framework系列】第6章 AMS原理之Launcher启动流程&#xff0c;大概了解了AMS的原理及启动流程&#xff0c;这一章节我们通过反射和动态代理对不同Android版本下的AMS进行Hook&#xff0c;实现…

一个tomcat部署两个服务的server.xml模板

一个服务的文件夹名字叫hospital&#xff0c;一个服务的文件夹叫ROOT&#xff0c;一个tomcat运行两个服务如何配置呢&#xff1f;注意一个appBase为webapps&#xff0c;另一个appBase为webapps1,当然也可以放在一个webappps里面。 <Service name"Catalina">&l…

几个似非而是的注释问题

C 语言的注释可以出现在 C 语言代码的任何地方。这句话对不对&#xff1f;这是我当学生时我 老师问的一个问题。我当时回答是不对。好&#xff0c;那我们就看看下面的例子&#xff1a; A &#xff09;&#xff0c; int/*...*/i; B &#xff09;&#xff0c; char* s"…