类的六个默认成员函数

news/2024/11/29 5:35:48/

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

如果一个类中什么成员都没有,简称为空类。空类中什么都没有吗?并不是的,任何一个类在我们不写的情 况下,都会自动生成下面6个默认成员函数。

image-20220416212744174

2.构造函数

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

class Date
{
public:Date(int year = 0,int month = 0,int day = 0)//构造函数(全缺省){_year = year;_month = month;_day = day;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};
int main()
{Date d1(2022, 2, 15);d1.Print();Date d2;d2.Print();return 0;
}

image-20220416214029326

构造函数的特性:

  1. 函数名与类名相同。
  2. 无返回值。
  3. 对象实例化时编译器自动调用对应的构造函数。
  4. 构造函数可以重载。
  5. 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成。编译器自动生成的默认构造函数不会初始化内置类型(基本类型),如:int , char , double等。但是会初始化我们的自定义类型。如我们用class,struct等定义的类型。
  6. 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。注意:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认成员函数。

哪些属于默认构造函数?

  • 我们没写编译器自己生成的
  • 我们写的无参的
  • 我们写的全缺省的

3.析构函数

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

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

  1. 析构函数名是在类名前加上字符 ~。
  2. 无参数无返回值。
  3. 一个类有且只有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。
  4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。
  5. 析构函数的调用也符合先进后出

4.拷贝构造函数

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

  1. 拷贝构造函数是构造函数的一个重载形式。
  2. 拷贝构造函数的参数只有一个且必须使用引用传参,使用传值方式会引发无穷递归调用。
  3. 若未显示定义,系统生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷,贝这种拷贝我们叫做浅拷贝或者值拷贝。

image-20220417203225232

从此以后注意,函数传参,自定义类型的对象,一般推荐引用传参。如果还要继续使用传值传参,也不是不可以,但是每次调用都会调用拷贝构造

5.运算符重载

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

函数名字为:关键字operator后面接需要重载的运算符符号。

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

image-20220417205259546

注意:

1.不能通过连接其他符号来创建新的操作符:比如operator@

2.重载操作符必须有一个类类型或者枚举类型的操作数

3.用于内置类型的操作符,其含义不能改变,例如:内置的整型+,不能改变其含义

4.作为类成员的运算符重载函数时,操作符有一个默认的形参this,限定为第一个形参

5…* 、:: 、sizeof 、?: 、. 注意这5个运算符不能重载。

6.&重载和const&重载

这两个默认成员函数一般不用重新定义 ,编译器默认会生成。

image-20221213235438762

7.练习编写默认成员函数

我们以实现一个日期类为例,练习一下

Date.h

#pragma once
#include <iostream>using std::cin;
using std::cout;
using std::endl;bool IsLeapYear(const int year);
int GetMonthDay(const int year, const int month);
class Date
{
public:Date(int year = 0, int month = 1, int day = 1){_year = year;_month = month;_day = day;}//Date类成员只有三个int,不需要写析构函数和拷贝构造Date& operator=(const Date& d){_year = d._year;_month = d._month;_day = d._day;return *this;   //这个函数之所以要有返回值,是为了解决  d3 = d2 = d1 这种情况}&重载和const&重载  这两个默认成员函数绝大多数情况下不需要自己写//Date* operator&()//{//	return this;//}//const Date* operator&()const//{//	return this;//}//日期的比较函数  这几个函数都比较短,直接定义在类里面了,在类里面定义的函数默认是内联函数bool operator>(const Date& d)const{if (_year > d._year)return true;if (_year == d._year && _month > d._month)return true;if (_year == d._year && _month == d._month && _day > d._day)return true;return false;}bool operator==(const Date& d)const{return _year == d._year&& _month == d._month&& _day == d._day;}bool operator<(const Date& d)const{if (*this > d || *this == d)return false;return true;}bool operator>=(const Date& d)const{if (*this < d)return false;return true;}bool operator<=(const Date& d)const{if (*this > d)return false;return true;}bool operator!=(const Date& d)const{if (*this == d)return false;return true;}//日期+-天数Date& operator+=(int day);Date operator+(int day)const;Date& operator-=(int day);Date operator-(int day)const;//日期前置++--和后置++--//为了区分前置和后置,有这样一个约定,在重载后置++--多一个int参数//由于前置++返回的是++后的值,可以传引用返回,而后置返回的是++之前的值,需要先创建一个临时变量保存++之前的值,在传值返回//前置++--相比于后置少了两次拷贝构造,效率稍微高一些Date& operator++();Date operator++(int);Date& operator--();Date operator--(int);//两个日期差多少天int operator-(const Date& d)const;void Print()const //这个const修饰的是this指针,使this指针指向的内容不能被修改的{cout << _year << "-" << _month << "-" << _day << endl;}
private:int _year;int _month;int _day;
};

Date.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include "Date.h"bool IsLeapYear(const int year)
{if (year % 4 == 0 && year % 100 != 0)return true;if (year % 400 == 0)return true;return false;
}
int GetMonthDay(const int year, const int month)
{const static int arr[] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };int days = arr[month];if (IsLeapYear(year) && month == 2)days += 1;return days;
}
Date& Date::operator+=(int day)
{while (day--){_day++;if (_day > GetMonthDay(_year, _month)){_month++;_day = 1;if (_month > 12){_year++;_month = 1;}}}return *this;
}Date Date::operator+(int day)const
{//我们知道i+12不影响i的值,所以为了不改变原来的Date的值,我们先拷贝构造一个,并且这里不能传引用返回,因为copy是局部变量Date copy = *this;copy += day;return copy;
}Date& Date::operator-=(int day)
{while (day--){_day--;if (_day == 0){_month--;if (_month == 0){_year--;_month = 12;}_day = GetMonthDay(_year, _month);}}return *this;
}Date Date::operator-(int day)const
{Date copy = *this;copy -= day;return copy;
}Date& Date::operator++()
{*this += 1;return *this;
}Date Date::operator++(int)
{Date copy = *this;*this += 1;return copy;
}Date& Date::operator--()
{*this -= 1;return *this;
}
Date Date::operator--(int)
{Date copy = *this;*this -= 1;return copy;
}int Date::operator-(const Date& d)const
{//让小的日期++,直到和大的日期相等为止int count = 0;int flag = -1;Date min = *this;Date max = d;if (min > max){min = d;max = *this;flag = 1;}while (min < max){min++;count++;}return flag * count;
}

http://www.ppmy.cn/news/3342.html

相关文章

[附源码]Node.js计算机毕业设计房屋中介管理信息系统Express

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

对数据库索引的理解以及索引在MySQL中的数据结构

引言 索引在本质上相当于书的目录&#xff0c;通过目录就可以快速的找到某个章节对应的位置。索引的效果&#xff0c;就是加快了查找的速度。日常进行数据库的操作&#xff0c;一般地都是进行增删查改&#xff0c;而在很多场景中&#xff0c;进行查找的概率要比增删改大很多。…

java.security.NoSuchProviderException: no such provider: BC

1.问题描述&#xff1a;支付宝支付回调验签的时候出现错误&#xff1a;java.security.NoSuchProviderException: no such provider: BC 2.解决方法&#xff1a;引入下面依赖包 <dependency> <groupId>org.bouncycastle</groupId> &…

Go1.19.3 数组与切片原理简析

数组 Go语言数组&#xff0c;声明有如下几种方式&#xff1a; var arr1 [10]intarr1[0] 10000var arr2 [10]int{0:0,2:2}var arr3 [...]int{1,2,3}其中arr1只是进行声明&#xff0c;数组在声明时&#xff0c;内存空间已经被开辟过&#xff0c;所以可以赋值。arr2是声明的同…

Linux基本指令(2)

Linux基本指令(2) &#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;Linux &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 本博客将展示25-30个LInux中常用的命令&#xff0c;…

SparkSQL 数据清洗API

文章目录常见数据清洗APIdropDuplicates数据去重dropna缺失值处理fillna缺失值填充Shuffle分区数目常见数据清洗API 在我们进行数据处理的时候&#xff0c;往往很多数据都是杂乱无章的数据&#xff0c;所以我们在处理数据时需要对数据进行预处理操作&#xff08;数据清洗&…

混检阳性概率的计算(贝叶斯定理的一个应用例)

目录 1. 混检阳性概率的计算 2. 混管阳性时你阳性的概率有多大&#xff1f; 2.1 贝叶斯分析结果的解释 1. 混检阳性概率的计算 目前核酸混检的基本做法是十混一&#xff0c;如果阳性人群分布完全随机&#xff0c;那么做十混一混检为阳性的概率有多大呢&#xff1f; …

android studio 如何不同版本的包重复引用

如何查找重复包 如何设置gradle工具 编译报错&#xff0c;原因是引用了不同版本的包。但是代码全局搜索只发现一个地方implementation了包。 1、首先要确保android studio->setting里面开启了build gradle task list 2、gradle列表里面要取消选中offline 3、点击gradle-&…