类和对象(二) - 实践
一、默认成员函数
什么是默认成员函数:用户不自己显示写,编译器默认生成的成员函数就是默认成员函数。
下面是 8 个默认成员函数
- 默认构造函数:用于创建对象时初始化对象。如果没有为类定义构造函数,编译器会自动生成一个默认构造函数。
- 析构函数:用于在对象生命周期结束时进行清理工作。如果没有定义析构函数,编译器也会提供一个默认的析构函数。
- 拷贝构造函数:用于创建一个新对象,该对象是其参数(另一个同类型对象)的副本。如果没有显式定义,编译器会生成一个默认的拷贝构造函数。
- 拷贝赋值运算符:用于将一个对象的值赋给另一个同类型的对象。如果没有显式定义,编译器会生成一个默认的拷贝赋值运算符。
- 移动构造函数:C++11 引入,用于通过移动而非复制的方式转移资源。如果没有定义,编译器会生成一个默认的移动构造函数(仅当类中没有定义任何构造函数时)。
- 移动赋值运算符:C++11 引入,用于通过移动而非复制的方式转移资源给另一个对象。如果没有定义,编译器会生成一个默认的移动赋值运算符(仅当类中没有定义任何赋值运算符时)。
- 类型转换运算符:允许类的对象被用作其他类型。例如,可以将类的一个对象用作内置类型(如int或double)。
- 虚析构函数:当类包含虚函数时,析构函数通常被声明为虚函数,以支持多态删除。虽然这不是一个默认成员函数,但它是与虚拟函数相关的一个重要概念。
其中 5,6 为 C++ 11 加入,7,8 不是很重要,因此下面介绍前四个。
对于编译器自己生成的函数我们需要了默认生成的函数的行为是什么,能否满足我们的需要,如果不满足自己显示写该如何写。
(一)、构造函数
- 构造函数并不是构造一个对象,它的作用类似于 stack 的 Init 函数,是完成对象的初始化工作。
- 构造函数的特点(也可以说是定义的方式)
- 函数名和类名相同。
- 没有返回值。
- 可以重载。
- 对象定义的时候自动调用。
- 用户不自己写编译器会自己生成。
- 编译器生成构造函数的行为
- 内置类型不做处理。
- 自定义类型调用他们的构造函数。
- 无参、全缺省、编译器自动生成的这三位构造函数叫做默认构造函数(其实就是不传参的),如果用户在定义对象的时候什么都不传编译器会自动调用默认构造函数,前两个和编译器生成的那个不能同时存在,无参和全缺省的虽然构成函数重载但是调用会存在歧义。
#include <iostream>using namespace std;class Date{public:Date(int year = 1, int month = 1, int day = 1){_year = year;_month = month;_day = day;}void print(){cout << _year << " " << _month << " " << _day << endl;}private:int _year;int _month;int _day;};int main(){//Date d1(); // 不能这样定义,会和函数声明分不清Date d1;d1.print();Date d2(2025, 11, 12);d2.print();return 0;}
(二)、析构函数
- 析构函数的作用也不是销毁一个对象,而是在对象声明周期结束的时候清理对象中所调用的资源。
- 析构函数的特点(定义方式)
- 函数名为:~类名。
- 没有参数。
- 没有返回值。
- 对象声明周期结束的时候自动调用。
- 不写编译器会自动生成,其行为对于内置类型不做处理,对于自定义类型调用他们的析构函数。一般没有资源占用的可以不写,编译器生成的就够用了,但是像 stack 这样的需要申请堆上的空间的类需要自己实现来完成资源的释放。
- C++ 规定对于多个对象,后定义的先析构。
#include <iostream>#include <stdlib.h>using namespace std;class Stack{public:Stack(int n = 4){cout << "Stack(int n = 4)" << endl;_a = (int*)malloc(sizeof(int) * n);_capacity = n;_size = 0;}~Stack(){cout << "~Stack()" << endl;free(_a);_a = nullptr;_capacity = 0;_size = 0;}private:int* _a;int _size;int _capacity;};class Date{public:Date(int year = 1, int month = 1, int day = 1){// 构造函数会先调用自定义类型的构造函数cout << "Date(int year = 1, int month = 1, int day = 1)" << endl;_year = year;_month = month;_day = day;}~Date(){// 析构函数后调用自定义类型的析构函数cout << "~Date" << endl;// 内置类型不做处理// 自定义类型调用他们的析构函数}void print(){cout << _year << " " << _month << " " << _day << endl;}private:int _year;int _month;int _day;Stack st;};int main(){Date d1;return 0;}
(三)、拷贝构造
- 拷贝构造的功能是用另外一个对象创建初始化一个新的对象。
- 拷贝构造是构造函数的一个重载函数,它的参数固定为自身类型的重载,外加一些有缺省值的参数。
- 如果参数不是自身类型的引用,传值传参或者传值返回会调用拷贝构造,这样就会递归下去,因此这样写不合法。
- 若为显示定义拷贝构造编译器会自动生成,对内置类型完成浅拷贝工作,自定义类型调用他们的拷贝构造。
- 对于一些指向资源的类型,单单的浅拷贝会导致这些成员指向同一块空间,这时需要深拷贝来为成员变量重新申请空间。
#include <iostream>using namespace std;class Date{public:// 构造函数Date(int year = 1, int month = 1, int day = 1, int n = 4){_year = year;_month = month;_day = day;_size = n;_a = (int*)malloc(n * sizeof(int));}void print(){cout << _year << '/' << _month << '/' << _day << '/' << endl;}// 拷贝构造//Date(const Date d) // 这样写会无穷递归Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;_size = d._size;// 针对于指向资源成员的拷贝不能用浅拷贝,因为资源是相互独立的// 可以为这个对象重新分配资源_a = (int*)malloc(d._size * sizeof(int));}~Date(){free(_a);_a = nullptr;}private:int _year;int _month;int _day;int* _a;int _size;};int main(){Date d1(2025, 1, 1); // 构造Date d2(d1); // 拷贝构造Date d3 = d1; // 拷贝构造 return 0;}
(四)、赋值运算符重载
1. 运算符重载
- C 语言的运算符对于自定义类型的不可用,C++ 允许用户自定义这些运算符的行为,使其满足用户自己逻辑上的行为,这个过程就叫做运算符的重载。
- 运算符重载是具有特殊名字的函数,它的名字是由operator和后面要定义的运算符共同构成。和其他函数一样,它也具有返回类型和参数列表以及函数体。
- 运算符重载的参数数量要求和操作数的数量一致,两个或以上的操作数要求运算符使用是参数的位置和参数列表的位置严格匹配。
- 如果把运算符重载函数定义在类的外面会导致私有的成员变量无法访问,可以通过函数返回成员变量拷贝、友元、重载成成员函数的方式解决,一般会选择最后一种。
- 成员函数会默认传 this 指针,因此第一个运算对象会传给 this,重载时参数的数量为运算数数量减一。
- 运算符重载后,优先级和结合性和原来保持一致。
- 运算符重载仅支持重载存在的运算符,不支持创建新的运算符。
- .* **:: sizeof ?: . **不支持重载。
- 重载的运算符必须有一个自定义类型,也就是说不能重载内置类型的运算符(你不能比祖师爷更懂运算符!!!)。
- 重载前置++ 和 后置++ 时,为了区分,后置++ 用一个类型为 int 的形参强行构成重载。
- 重载 << 和 >> 时,需要重载成全局函数,因为流插入和提取的方向时指向流对象的,如果重载成成员函数第一个参数为 this 指向就反了(如果你是左撇子当我没说)。
2. 赋值运算符重载
赋值运算符重载用于已经存在的两个对象的拷贝。
- 赋值运算符重载是一个运算符重载,规定必须为成员函数。赋值运算符重载的参数建议为const 自身类型的引用, 减少传参拷贝。
- 有返回值,建议写成自身类型的引用,这样就既可以减少拷贝,又能支持连续的赋值。
- 没有显示写,编译器生成的赋值运算符重载的行为是对内置类型不做处理,自定义类型调用他们的赋值运算符重载。
- 还是那句话,如果类对象有指向什么资源就自己实现,否则编译器生成的就够用。
(五)、取地址运算符重载
- 这个成员函数编译器默认生成的就够用,普通成员函数的 this 指针类型为 Date const * ,即指针的指向不能改变。
- const 成员变量的 this 类型为 const Date * const ,指向的内容也不能改变。
- 由于 this 不能显示写,如果想限制 this 指向的内容不能修改,要在成员函数参数列表的后面加上 const,这种成员函数叫做 const 成员函数。
二、日期类的实现
#include "Date.h"
Date::Date(int year, int month, int day)
{
_year = year;
_month = month;
_day = day;
if (!checkdate())
{
cout << "非法日期:" << *this << endl;
}
}
Date::Date(const Date& d)
{
_year = d._year;
_month = d._month;
_day = d._day;
}
void Date::print() const
{
cout << _year << '/' << _month << '/' << _day << endl;
}
bool Date::checkdate() const
{
return (_month >= 1 && _month <= 12 && _day >= 1 && _day <= get_monthday());
}
bool Date::operator==(const Date& d) const
{
return (_year == d._year)
&& (_month == d._month)
&& (_day == d._day);
}
bool Date::operator!=(const Date& d) const
{
return !(*this == d);
}
bool Date::operator<(const Date& d) const
{
if (_year != d._year) return _year < d._year;
if (_month != d._month) return _month < d._month;
if (_day != d._day) return _day < d._day;
return false;
}
bool Date::operator<=(const Date& d) const
{
return (*this < d) || (*this == d);
}
bool Date::operator>(const Date& d) const
{
return !(*this <= d);
}
bool Date::operator>=(const Date& d) const
{
return !(*this < d);
}
Date& Date::operator+=(const int day)
{
if (day < 0) return *this -= -day;
_day += day;
int monthday = -1;
while (_day > (monthday = this->get_monthday()))
{
_day -= monthday;
_month++;
if (_month == 13)
{
_month = 1;
_year++;
}
monthday = this->get_monthday();
}
return *this;
}
Date Date::operator+(const int day) const
{
Date tmp(*this);
tmp += day;
return tmp;
}
Date& Date::operator-=(const int day)
{
if (day < 0) return *this += -day;
_day -= day;
int monthday = -1;
while (_day <= 0)
{
_month--;
if (_month <= 0)
{
_year--;
_month = 12;
}
monthday = this->get_monthday();
_day += monthday;
}
return *this;
}
Date Date::operator-(const int day) const
{
Date tmp(*this);
tmp -= day;
return tmp;
}
Date& Date::operator--()
{
*this -= 1;
return *this;
}
Date Date::operator--(int)
{
Date tmp(*this);
*this -= 1;
return tmp;
}
Date& Date::operator++()
{
*this += 1;
return *this;
}
Date Date::operator++(int)
{
Date tmp(*this);
*this += 1;
return tmp;
}
int Date::operator-(Date& d) const
{
Date tmp1(*this);
if (tmp1 < d) return -(d - tmp1);
// d > *this
int day = 0;
while (d != tmp1)
{
day++;
tmp1--;
}
return day;
}
ostream& operator<<(ostream& out, const Date& d)
{
out << d._year << "年" << d._month << "月" << d._day << "日" << endl;
return out;
}
istream& operator>>(istream& in, Date& d)
{
cout << "请输入日期:" << endl;
while (1)
{
in >> d._year >> d._month >> d._day;
if (d.checkdate())
{
break;
}
else
{
cout << "非法日期请重新输入" << endl;
}
}
return in;
}
#pragma once
#include <iostream>#include <assert.h>using namespace std;class Date{// 友元函数声明// 允许类外函数访问类的私有成员friend ostream& operator<<(ostream& out, const Date& d);friend istream& operator>>(istream& in, Date& d);public:Date(int year = 1, int month = 1, int day = 1);Date(const Date& d);void print() const;bool checkdate() const;int get_monthday() const{assert(_year > 0 && _month <= 12 && _month >= 1);static int monthday[13] = { -1, 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 monthday[_month];}//// 取地址运算符重载//Date* operator&()//{// return this;//}//const Date* operator&() const//{// return this;//}bool operator==(const Date& d) const;bool operator!=(const Date& d) const;bool operator<(const Date& d) const;bool operator<=(const Date& d) const;bool operator>(const Date& d) const;bool operator>=(const Date& d) const;Date& operator+=(const int day);Date operator+(const int day) const;Date& operator-=(const int day);Date operator-(const int day) const;int operator-(Date& d) const;Date& operator--(); // 前置Date operator--(int); // 后置Date& operator++();Date operator++(int);private:int _year;int _month;int _day;};ostream& operator<<(ostream& out, const Date& d);istream& operator>>(istream& in, Date& d);
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/936014.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!相关文章
2025 年国内风化板源头厂家最新推荐排行榜:聚焦优质原料与精湛工艺,助力消费者精准选购靠谱企业榜单吧台/松木/桌面/茶台风化板厂家推荐
引言当前风化板市场需求持续增长,但行业乱象也让消费者选购时倍感困扰。一方面,大量厂家涌入导致产品质量参差不齐,部分企业为压缩成本使用劣质木材,使风化板易出现变形、开裂问题,严重影响使用体验;另一方面,市…
20232312 2025-2026-1 《网络与系统攻防技术》实验一实验报告
20232312 2025-2026-1 《网络与系统攻防技术》实验一实验报告20232312 2025-2026-1 《网络与系统攻防技术》实验一实验报告
1.实验内容
1.1通过学习、分析可执行文件pwn1,学习了三种漏洞利用技术:直接修改程序机…
2025年10月方钢厂家最新推荐排行榜,热轧方钢,冷拉方钢,高强度方钢,优质方钢供应商推荐!
2025年10月方钢厂家最新推荐排行榜:热轧方钢、冷拉方钢、高强度方钢、优质方钢供应商推荐随着工业和建筑业的快速发展,方钢作为重要的建筑材料之一,其需求量持续增长。为了帮助筛选方钢品牌,特此发布权威推荐榜单,…
OpenBLAS blas_thread_init: pthread_create failed for thread 1 of 4: Operation not permitted
https://blog.csdn.net/qq_45237725/article/details/148383599 (加权限)无可奈何花落去,似曾相识燕归来
QPSK调制在瑞利、高斯和莱斯信道下的MATLAB仿真
QPSK调制在不同信道条件下性能仿真的MATLAB实现
%% QPSK在瑞利、高斯和莱斯信道下的仿真
clear; close all; clc;%% 仿真参数设置
numBits = 1e6; % 传输的比特数
SNR_dB = 0:2:20; % 信噪比范…
Delapp文件删除工具!Windows中删除文件和文件夹的简单工具!仅507KB的工具小巧且方便
有的时候我们删文件总是遇到无法删除,提示文件在另一程序打开,但是又没有打开,怎么删也删不掉,
软件介绍
Delapp 是一款开源免费的Windows文件删除工具,免安装、小巧、速度快、支持win7……帮你解除占用,爽…
在 2023 年屌爆了一整年的 shadcn/ui 用的 Headless UI 到底是何方神圣?
在 2023 年屌爆了一整年的 shadcn/ui 用的 Headless UI 到底是何方神圣?
2024-03-1113,974阅读8分钟
专栏:
Headless UI 无头组件的介绍与实现 作者:易师傅 、github
声明:本文为稀土掘金技术社区首发签约文章…
基于Hadoop+Spark的商店购物趋势分析与可视化平台科技达成
基于Hadoop+Spark的商店购物趋势分析与可视化平台科技达成pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consola…
2025 年折弯厂家推荐:江阴市富磊钢板加工专业中厚钢板折弯加工与高效行业解决方案提供商
行业背景随着船舶设备、港口重工、换热设备、环保设备等重工行业的快速发展,市场对中厚钢板折弯加工的需求日益提升,尤其是超厚、超长、大吨位的钢板折弯加工需求,对加工企业的技术实力、设备配置和产能规模提出了更…
2025年10月振动电机厂家最新推荐排行榜,三相振动电机,单相振动电机,防爆振动电机公司推荐!
2025年10月振动电机厂家最新推荐排行榜:三相、单相及防爆振动电机公司推荐随着工业自动化和智能化的不断发展,振动电机在各个行业的应用越来越广泛。从矿山、冶金到食品加工、化工等领域,振动电机都发挥着重要作用。…
2025 储能 EMS 厂商排名:五大品牌以全维度优势领跑,技术与规模双驱动企业凸显
在新型电力系统建设加速推进的背景下,储能 EMS 作为储能电站的 “大脑”,其厂商的综合实力直接决定系统运行效率与价值实现。2025 年市场竞争已从场景适配转向全维度实力比拼,资质认证的完备性、核心技术的突破性、…
【IEEE出版、连续6届已EI检索、多校联办】第七届机器人、智能控制与人工智能国际学术会议(RICAI 2025)
第七届机器人、智能控制与人工智能国际学术会议(RICAI 2025)
2025 7th International Conference on Robotics, Intelligent Control and Artificial Intelligence
IEEE出版(ISBN: 979-8-3315-6934-1),IEEE Xplor…
企业数字化转型浪潮下,如何选择最适合的项目管理工具?
企业数字化转型浪潮下,如何选择最适合的项目管理工具?
随着数字化转型进程加速,项目管理工具已成为企业提升协作效率的关键基础设施。根据Gartner最新调研数据,2023年全球项目管理软件市场规模达到59亿美元,年增长…
dify工作流遇到的问题及解决方案
dify工作流遇到的问题及解决方案1、在通过dify粘贴文件url上传时遇到的报错:报错显示无效的url,在浏览器输入这串url能获取到文件,说明是dify读取文件的问题
通过浏览器开发者模式可以得出结果:缺少本地url头
在di…
2025年10月青海视频号运营最新权威推荐榜:专业服务与创意内容引领潮流!
2025年10月青海视频号运营最新权威推荐榜:专业服务与创意内容引领潮流!随着移动互联网的快速发展,短视频平台已经成为企业宣传和品牌推广的重要渠道。在青海地区,视频号作为一种新兴的营销工具,正逐渐受到越来越多…
2025 年玻璃钢水箱生产厂家最新推荐榜单:含 30 吨 / 订做 / 消防 / 方形 / 拼装式 / 屋顶 / 大型产品,从产能与服务维度精选优质企业
当前建筑、化工、食品、医药等行业对玻璃钢水箱的需求日益增长,但市场乱象却让采购者陷入困境。多数厂家存在技术储备薄弱问题,产品质量波动大,难以满足行业严苛标准;部分厂家服务体系残缺,售前咨询模糊、售后响应…
[C++工程框架]gflags和gtest的简单介绍
[C++工程框架]gflags和gtest的简单介绍2025-10-13 11:21
tlnshuju
阅读(0)
评论(0) 收藏
举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !…
2025 年水下打捞/打捞手机/打捞黄金/打捞戒指公司推荐榜:聚焦专业与高效,助您精准匹配靠谱服务
随着水上作业场景多元化、个人水下财物保护需求提升及航运事业的蓬勃发展,水下打捞服务已从专业工程领域逐步延伸至民用应急场景,2025 年国内水下打捞市场规模预计持续扩容。但市场快速发展也催生了资质不全、技术薄…
2025年10月通风气楼厂家最新推荐排行榜,工业/商用通风气楼,高效节能通风解决方案提供商!
2025年10月通风气楼厂家最新推荐排行榜,工业/商用通风气楼,高效节能通风解决方案提供商!随着工业和商业建筑对空气质量要求的不断提高,通风气楼作为重要的通风设备,其市场需求也在不断增长。为了帮助筛选通风气楼…