默认成员函数

news2024/11/18 17:28:57

前文提要

本文全文以日期类为例
先简单写一个日期类

class Data{
public:


private:
	int _year;
	int _month;
	int _day;
};

且补充一个小知识

数据类型的划分

内置类型:是编程语言提供的基本数据类型,例如整数、浮点数、字符、布尔值
自定义类型:是开发人员根据应用程序的需求定义的类型,它可以由内置类型组成,也可以由其他自定义类型组成。自定义类型可以通过类、结构体、枚举等方式进行定义。

默认成员函数

默认成员函数是一些 当我们什么都没有编写时,也会自动在类中生成的函数

构造函数

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

特征

  1. 函数名与类名相同。
  2. 无返回值。
  3. 对象实例化时编译器自动调用对应的构造函数。

由上述三条可知构造函数的基本特质
先写一个简单的构造函数

	//函数名与类名相同 且 无返回值
	Date()
	{
		_year = 0;
		_month = 0;
		_day = 0;
	}
  1. 构造函数可以重载。

构造函数可以支持重载的化,便可以支持各种各样的初始化

// 1.无参构造函数
 Date()
 {}
 // 2.带参构造函数
 Date(int year, int month, int day)
 {
 _year = year;
 _month = month;
 _day = day;
 }
 //全缺省的构造
  Date(int year = 0, int month = 0, int day = 0)
 {
 _year = year;
 _month = month;
 _day = day;
 }
 //半缺省的构造
  Date(int year, int month = 0, int day = 0)
 {
 _year = year;
 _month = month;
 _day = day;
 }
  1. 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,一旦用户显式定义编译器将不再生成
  2. 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。
    由于构造函数是对象实例化时编译器自动调用
    虽然无参的构造函数与全缺省的构造函数满足函数重载的要求。
    但不满足构造函数的要求,全缺省与无参的函数会引起歧义
    当函数调用不传参数时,编译器无法识别调用哪个构造函数
    在这里插入图片描述

默认构造函数

是一个在创建对象时被自动调用的特殊的构造函数。它通常没有任何参数,并且不执行任何特定的初始化操作。默认构造函数的作用是初始化对象的成员变量,确保对象在创建时处于一个合理的状态。

无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数。

默认构造函数由编译器自动生成的构造函数,是一个无参的构造函数
构造函数中对于成员对象的处理根据成员对象的类型分为两类
内置类型不处理
自定义类型调用自定义类型的默认构造函数
也因此,建议每个函数都提供默认构造函数。
此外,因内置类型不予处理,c++也时常被人诟病
在C++11 中针对内置类型成员不初始化的缺陷,又打了补丁,即:内置类型成员变量在类中声明时可以给默认值。

故而,整体上我们日期类的构造函数

Date(int year = 1900, int month = 1, int day = 1)
	// 拷贝构造函数Date::Date(int year , int month, int day)
{
	_year = year;
	_month = month;
	_day = day;
}

析构函数

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

特征

  1. 析构函数名是在类名前加上字符 ~。
  2. 无参数无返回值类型。
  3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重
  4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。
  5. 如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如Date类;
  6. 有资源申请时,一定要写,否则会造成资源泄漏,比如Stack类

回到我们的例子来
Date没有申请空间,析构函数是可以不写的

拷贝构造

只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时由编译器自动调用。

特征

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

按定义可知,拷贝构造中有且只含有一个参数->类类型对象
如果直接传类类型对象本身,传值的过程本身就是一次类对象的拷贝
也不可避免的会引起无穷递归调用

  1. 若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。
    类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请时,则拷贝构造函数是一定要写的

  2. 拷贝构造函数典型调用场景:

  • 使用已存在对象创建新对象
  • 函数参数类型为类类型对象
  • 函数返回值类型为类类型对象

回到例子上来
日期类没有设计资源申请,默认的拷贝函数也足以满足需求

赋值重载

赋值重载也可以是一种特殊的默认成员函数,不手动书写时,会在类中自动生成。具体在操作符重载中细说

运算符重载

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

原型

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

注意

  • 不能通过连接其他符号来创建新的操作符:比如operator@
  • 重载操作符必须有一个类类型参数
  • 用于内置类型的运算符,其含义不能改变,例如:内置的整型+,不 能改变其含义
  • 作为类成员函数重载时,其形参看起来比操作数数目少1,因为成员函数的第一个参数为隐藏的this
  • .* :: sizeof ?: .注意以上5个运算符不能重载。这个经常在笔试选择题中出现。

赋值运算符的重载

格式

参数类型:const T&,传递引用可以提高传参效率
返回值类型:T&,返回引用可以提高返回的效率,有返回值目的是为了支持连续赋值
检测是否自己给自己赋值
返回*this :要复合连续赋值的含义

特征

  1. 赋值运算符只能重载成类的成员函数不能重载成全局函数

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

2.用户没有显式实现时,编译器会生成一个默认赋值运算符重载,以值的方式逐字节拷贝 (与默认拷贝构造类似)

回到例子上来,与拷贝构造同理

前置++ 与 后置++

前置++和后置++都是一元运算符
为了让前置++与后置++形成能正确重载

C++规定:后置++重载时多增加一个int类型的参数,但调用函数时该参数不用传递,编译器自动传递

注意:后置++是先使用后+1,因此需要返回+1之前的旧值,故需在实现时需要先将this保存一份,然后给this+1
以日期类未例

 	// 前置++
	Date& operator++()
	{
		return (*this) += 1;
	}
	// 后置++
	Date operator++(int)
	{
		Date tmp = *this;
		*this += 1;
		return tmp;
	}

日期类的实现

Date.cpp

#include"Data.h"
// 获取某年某月的天数
int Date::GetMonthDay(int year, int month)
{
	static int days[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };
	int day = days[month];
	if ((month == 2) && (((year % 4 == 0) && (year % 100 != 0)) || year % 400 == 0))
	{
		day++;
	}
	return day;
}
// 全缺省的构造函数
Date::Date(int year , int month, int day)
{
	_year = year;
	_month = month;
	_day = day;
}
// d2(d1)
Date::Date(const Date& d)
{
	_year = d._year;
	_month = d._month;
	_day = d._day;
}

Date.h

#pragma once
#include<iostream>
using namespace std;
class Date
{

public:
	// 获取某年某月的天数
	int GetMonthDay(int year, int month);
	// 全缺省的构造函数
	Date(int year = 1900, int month = 1, int day = 1);
	// 拷贝构造函数
  // d2(d1)
	Date(const Date& d);
	// 赋值运算符重载
  // d2 = d3 -> d2.operator=(&d2, d3)
	Date& operator=(const Date& d)
	{
		_year = d._year;
		_month = d._month;
		_day = d._day;
		return *this;
	}
	// 析构函数
	~Date()
	{

	};
	// 日期+=天数
	Date& operator+=(int day)
	{
		_day += day;
		while (_day > GetMonthDay(_year, _month))
		{
			_day -= GetMonthDay(_year, _month);
			_month++;
			if (_month == 13)
			{
				_month = 1;
				_year++;
			}
		}
		return *this;
	}
	void days()
	{
		int day = _day;
		for (int i = 1; i < _month; i++)
		{
			day += GetMonthDay(_year, i);
		}
		cout << "侯稼澍" << _year << ":" << _month << ":" << _day << "为第" << day << "天" << endl;

	}
	void print()
	{
		cout << _year << " " << _month << " " << _day << endl;
	}
	// 日期+天数
	Date operator+(int day)
	{
		Date tmp = *this;
		return tmp += day;
	}
	// 日期-天数
	Date operator-(int day)
	{
		Date tmp = *this;
		return tmp -= day;
	}
	// 日期-=天数
	Date& operator-=(int day)
	{
		_day -= day;
		while (_day <= 0)
		{
			_month--;
			if (_month == 0)
			{
				_month = 12;
				_year--;
			}
			_day += GetMonthDay(_year, _month);
		}
		return *this;
	}
	// 前置++
	Date& operator++()
	{
		return (*this) += 1;
	}
	// 后置++
	Date operator++(int)
	{
		Date tmp = *this;
		*this += 1;
		return tmp;
	}
	// 后置--
	Date operator--(int)
	{
		Date tmp = *this;
		*this -= 1;
		return tmp;
	}
	// 前置--
	Date& operator--()
	{
		return *this -= 1;
	}
	// >运算符重载
	bool operator>(const Date& d)
	{
		if ((_year > d._year)
			|| (_year == d._year && _month > d._month)
			|| (_year == d._year && _month == d._month && _day > d._day))
			return true;
		else
			return false;
	}
	// ==运算符重载
	bool operator==(const Date& d)
	{
		return ((_year == d._year) && (_month == d._month) && (_day == d._day));
	}
	// >=运算符重载
	bool operator >= (const Date& d)
	{
		return (*this > d) || (*this == d);
	}
	// <运算符重载
	bool operator < (const Date& d)
	{
		return !(*this >= d);
	}
	// <=运算符重载
	bool operator <= (const Date& d)
	{
		return (*this < d) || (*this == d);
	}
	// !=运算符重载
	bool operator != (const Date& d)
	{
		return !(*this == d);
	}
	// 日期-日期 返回天数
	int operator-(const Date& d)
	{
		int count = 0;
		Date big = *this;
		Date small = d;
		if (small > big)
		{
			small = *this;
			big = d;
		}
		while (big != small)
		{
			small++;
			count++;
		}
		return count;
	}

private:

	int _year;

	int _month;

	int _day;

};

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

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

相关文章

FreeRTOS实时操作系统(十二)事件标志组

系列文章目录 文章目录 系列文章目录事件标志组事件标志组API函数实验测试 事件标志组 事件标志位&#xff1a;用一个位来表示事件是否可以发生。 事件标志组是一组事件标志位的集合 特点&#xff1a; 1.每一个位表示一个事件&#xff08;高8位不是&#xff09; 2.每一位事件…

Java的异常Exception

异常 1、异常概述与异常体系结构 1.1、异常概述 异常&#xff1a;在Java语言中&#xff0c;将程序执行中发生的不正常情况称为“异常”&#xff08;开发过程中的语法错误和逻辑错误不是异常&#xff09; Java程序在执行过程中所发生的异常事件可分为两类&#xff1a; Erro…

装饰器模式:通过剖析Java IO类库源码学习装饰器模式

我们通过剖析Java IO类的设计思想&#xff0c;再学习一种新的结构型模式&#xff0c;装饰器模式。它的代码结构跟桥接模式非常相似&#xff0c;不过&#xff0c;要解决的问题却大不相同。 Java IO类库非常庞大和复杂&#xff0c;有几十个类&#xff0c;负责IO数据的读取…

Appium: Windows系统桌面应用自动化测试(三) 【脚本操作】

Appium: Windows系统桌面应用自动化测试 【脚本操作】 一、常用操作1、添加被测程序1.1示例一&#xff1a;通过程序路径指定应用程序&#xff0c;例如指定写字板程序路径。1.2示例二&#xff1a;通过程序ID指定应用程序&#xff0c;例如指定计算器ID。1.3 应用程序ID&#xff0…

芯片工程师求职题目之验证篇(2)

1. 事件驱动的仿真器和和基于周期的仿真器有什么区别&#xff1f; 事件驱动的仿真器顾名思义就是根据事件(event)触发仿真进行的&#xff0c;在进入一个周期中&#xff0c;它会获取每个事件并通过设计传播求值&#xff0c;直到达到稳定状态的条件&#xff0c;接着进入下一个周…

Android:安卓开发采用Volley网络框架+MySQL数据库,实现从服务器获取数据并展示完成记单词APP

一、功能与要求 实现功能&#xff1a;设计一个记单词APP。服务器采用Tomcat&#xff0c;数据库采用Mysql。实现用户的注册登录功能以及单词的增删改查。 指标要求&#xff1a;实现UI布局&#xff1b;将系统数据保存到Mysql数据库中&#xff0c;并采用Volley网络框架实现从服务…

【机器学习核心总结】什么是随机森林

什么是随机森林 森林里有很多树&#xff0c;随机森林里有很多决策树。 随机森林是决策树的升级版&#xff0c;随机指的是树的生长过程。世上没有两片相同的树叶&#xff0c;随机森林中的树也各不相同。在构建决策树时&#xff0c;我们会从训练数据中有放回的随机选取一部分样本…

Kubernetes service服务的发布 - kube-proxy(负载均衡器)-IPVS

目录 Service Service将内部的pod暴露到外面&#xff0c;让用户可以访问 负载均衡策略&#xff1a; Service 的类型&#xff1a; 案例&#xff1a;Service服务发布案例 扩展&#xff1a;我们在案例再加入一个探针的使用 更改后的my_nginx.yaml文件&#xff1a; 创建Pod&…

ChatGLM2-6B发布,C-Eval超GPT4,支持32k上下文!

自清华大学数据挖掘实验室&#xff08;THUDM&#xff09;3月开源ChatGLM-6B已经过去了3个多月&#xff0c;最近他们又带来了性能全面提升的“船新”版本-ChatGLM2-6B。别看名字变化小&#xff0c;其实更新的模型性能是又有量又实用。不了解ChatGLM的小伙伴可以看我这篇文章&…

Java基础之五 反射

通过Java反射机制&#xff0c;可以在程序中访问已经装载到JVM中的Java对象的描述&#xff0c;实现访问、检测和修改描述Java对象本身信息的功能。 通过反射可以访问的主要描述信息 访问成员变量 常用方法&#xff1a;getFields()、getField(String name)、getDeclaredFields()…

第 353 场LeetCode周赛

A 找出最大的可达成数字 签到题 class Solution { public:int theMaximumAchievableX(int num, int t) {return numt*2;} };B 达到末尾下标所需的最大跳跃次数 动态规划: 定义 p i p_i pi​为跳至 i i i处所需的最大跳跃次数, 有状态转移方程 p i m a x { p j 1 ∣ 0 ≤ j &…

文档管理:PaperPort Professional 14.7 Crack

文档管理变得简单 PaperPort Professional 快速、轻松地访问重要文档对于保持组织平稳运行至关重要。与其浪费时间在文件夹中搜索所需的文件&#xff0c;不如在PC上扫描&#xff0c;转换&#xff0c;组织&#xff0c;组装和共享文档和图像&#xff0c;或者更好的是&#xff0c;…

vue对于数组的数据监听变化和object是不一样的吗?

我们知道vue对于数组的数据监听变化和object是不一样的&#xff0c;因为我们常说的Object.defineProperty是对象上面的方法&#xff0c;所以对于array数组需要实现另外一套变化侦测机制。 今天我们就来研究下。 在哪里收集依赖 array数据设计了新的变化侦测机制&#xff0c;…

阿里云服务器架构X86计算、ARM、GPU/FPGA、裸金属和超级计算集群

阿里云服务器架构有什么区别&#xff1f;X86计算、ARM计算、GPU/FPGA/ASIC、弹性裸金属服务器、超级计算集群有什么区别&#xff1f;阿里云服务器网分享云服务器ECS架构详细说明&#xff1a; 目录 阿里云服务器ECS架构说明 X86计算 ARM计算 GPU/FPGA/ASIC 弹性裸金属服务…

第八章:L2JMobius学习 – 游戏服务GameServer讲解

本章节我们来讲解GameServer服务&#xff0c;首先来查看它的文件结构 ai&#xff1a;游戏角色自动化处理&#xff0c;比如说&#xff0c;自动攻击。 cache&#xff1a;数据缓存&#xff0c;里面就一个HtmCache.java类&#xff0c;缓存HTML文件内容。 communitybbs&#xff1a;b…

【C语言】1-Visual C++ 2010 的简单使用和第一个 C 语言程序

1. Visual C++ 2010 的简单使用 1.1 面板介绍 1.2 新建C语言项目 打开 Visual C++ 2010,点击 New Project 根据下面的图示进行操作,其中需要注意 ③:这里输入的为项目名(建议和我的命名保持一致) ④:这里是项目存放的位置,可以自己选择,最好不要有中文路径(只要是使…

苹果用户要留意?女子FaceTime通话面临巨额骗局,损失高达160万

FaceTime通话是苹果提供的一项服务&#xff0c;可以让使用iOS、iPadOS设备或Mac电脑的用户进行视频或音频通话。只要知道对方的Apple ID&#xff0c;世界各地的苹果设备都可以通过该ID进行呼叫。 据报道&#xff0c;一名居住在上海金山的女性最近遭受了一种新型诈骗&#xff0c…

js逆向补环境-调试工具vscode与nodejs使用之无环境联调

目录 一、啊哈一、Nodejs安装1、nodejs最新版本的安装&#xff08;windows&#xff09;2、旧版nodejs更新成最新版本&#xff08;windows&#xff09;3、nodejs安装&#xff08;linux&#xff09; 二、vscode安装使用(windows)1、下载安装vscode2、vscode运行插件Code Runner安…

多元分类预测 | Matlab基于K近邻算法(KNN)的数据分类预测,多特征输入模型

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 基于K近邻算法(KNN)的数据分类预测,多特征输入模型 多特征输入单输出的二分类及多分类模型。程序内注释详细,直接替换数据就可以用。程序语言为matlab,程序可出分类效果图,迭代优化图,混淆矩阵图。 部分源码