c++类和对象(2)

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

在C++中,如果一个类没有显式定义某些成员函数,编译器会默认为这个类生成六个默认成员函数。以下是这六个默认成员函数:

默认构造函数(Default Constructor)

如果类没有定义任何构造函数,编译器会提供一个默认构造函数,这个默认构造函数是一个无参构造函数,它的作用是创建一个对象,并为对象的成员变量提供默认值。

析构函数(Destructor)

如果类没有定义析构函数,编译器会提供一个默认的析构函数,默认析构函数是一个空函数体,用于在对象生命周期结束时释放资源。

拷贝构造函数(Copy Constructor)

用于通过一个同类型的已存在对象来初始化一个正在创建的对象。默认的拷贝构造函数执行成员的逐位复制。

拷贝赋值运算符(Copy Assignment Operator)

用于将一个对象赋值给同类型的另一个已存在对象。默认的拷贝赋值运算符执行成员的逐位赋值。

移动构造函数(Move Constructor) (C++11及以后)

当需要通过一个临时对象来初始化同类型的另一个对象时,移动构造函数会被调用。默认的移动构造函数“窃取”临时对象的资源。

移动赋值运算符(Move Assignment Operator) (C++11及以后)

用于将一个临时对象赋值给同类型的另一个已存在对象。默认的移动赋值运算符也是“窃取”临时对象的资源。

2. 构造函数

构造函数是类的一个特殊成员函数,它的主要作用是在创建类的对象时初始化对象的成员变量。构造函数具有以下特点:

  1. 函数名称:构造函数的名称必须与类名相同。
  2. 参数:构造函数可以没有参数,也可以有多个参数,用于提供初始化成员变量的值。
  3. 返回类型:构造函数没有返回类型,即使是void也不可以。
  4. 作用:在对象创建时自动调用,用于初始化对象的成员变量。

默认构造函数

如果类没有定义任何构造函数,编译器会提供一个默认构造函数。如果定义了其他构造函数,但仍然需要一个无参的构造函数,则必须显式定义默认构造函数。

class MyClass {
public:MyClass() {// 默认构造函数的实现}
};

 参数化构造函数

允许在创建对象时传递参数,以初始化对象的成员变量。

class MyClass {
public:int x;MyClass(int val) : x(val) {// 参数化构造函数的实现}
};

 转换构造函数

允许通过一个不同类型的值来创建对象。

class MyClass {
public:MyClass(int val) {// 转换构造函数的实现}
};

 初始化列表

构造函数可以使用初始化列表来初始化成员变量,这通常比在函数体内赋值更高效。

class MyClass {
public:int x;MyClass() : x(10) {// 使用初始化列表}
};

3. 析构函数

析构函数是类的一个特殊成员函数,它的作用是在对象生命周期结束时执行必要的清理工作。析构函数具有以下特点:

  1. 函数名称:析构函数的名称是在类名前加上波浪号(~)。
  2. 参数:析构函数没有参数,因此不能被重载。
  3. 返回类型:析构函数没有返回类型,即使是void也不可以。
  4. 作用:在对象被销毁时自动调用,用于释放对象所占用的资源,如动态分配的内存、打开的文件句柄、网络连接等。

规则

  • 每个类只能有一个析构函数。
  • 如果类没有显式定义析构函数,编译器会自动生成一个默认的析构函数,该默认析构函数是一个空函数体。
  • 如果类中包含指向动态分配内存的指针成员,则通常需要定义一个自定义的析构函数来释放这些内存。
class MyClass {
public:MyClass() {// 构造函数的实现,可能包含动态内存分配}~MyClass() {// 析构函数的实现,释放动态分配的内存}
private:int* data; // 指向动态分配内存的指针
};int main() {MyClass obj; // 创建对象,调用构造函数// ... 使用对象 ...return 0; // 程序结束,obj对象生命周期结束,调用析构函数
}

4. 拷贝构造函数

拷贝构造函数是一种特殊的构造函数,它用于创建一个新对象作为另一个同类对象的副本。拷贝构造函数具有以下特点:

  1. 函数名称:拷贝构造函数的名称与类名相同,且有一个参数,该参数是对类类型对象的引用。
  2. 参数:拷贝构造函数的参数必须是类类型的引用,通常使用常量引用,以避免修改原对象,并允许传递临时对象。
  3. 返回类型:拷贝构造函数没有返回类型,即使是void也不可以。
  4. 作用:当需要通过已存在的对象来初始化一个新对象时,拷贝构造函数会被调用。
class MyClass {
public:MyClass(const MyClass& other) {// 拷贝构造函数的实现// 通常用于复制成员变量}// 其他成员函数和成员变量...
};

默认拷贝构造函数

如果类没有显式定义拷贝构造函数,编译器会自动生成一个默认的拷贝构造函数。默认拷贝构造函数执行成员的逐位复制(浅拷贝)。对于包含指针成员的类,默认拷贝构造函数可能会导致问题,因为它只会复制指针的值,而不是指针指向的数据。

自定义拷贝构造函数

在某些情况下,需要自定义拷贝构造函数来执行深拷贝,以确保每个对象都有自己独立的副本。

class MyClass {
public:int* data;MyClass(int value) : data(new int(value)) {}// 自定义拷贝构造函数MyClass(const MyClass& other) : data(new int(*other.data)) {// 执行深拷贝}~MyClass() {delete data; // 释放动态分配的内存}
};

5. 赋值运算符重载

在C++中,赋值运算符 = 可以被重载以定制对象之间的赋值行为。当你定义了一个类,并且希望对象能够使用 = 运算符进行赋值时,你可能需要重载赋值运算符。

  1. 参数类型:赋值运算符重载函数应该有一个参数,该参数是类类型的引用。通常使用常量引用,以允许传递临时对象,并防止在赋值过程中修改右操作数。

  2. 返回类型:赋值运算符重载函数应该返回一个指向当前对象的引用,通常是一个 *this 指针。

  3. 函数名称:赋值运算符重载的函数名是 operator=

  4. 成员函数:赋值运算符必须是类的成员函数。

class MyClass {
public:int* data;MyClass(int value) : data(new int(value)) {}// 赋值运算符重载MyClass& operator=(const MyClass& other) {if (this != &other) { // 避免自我赋值delete data;      // 删除旧值data = new int(*other.data); // 深拷贝}return *this; // 返回当前对象的引用}~MyClass() {delete data; // 析构函数中释放动态分配的内存}
};

 

注意事项:

  • 自我赋值检查:在赋值运算符的实现中,检查自我赋值是非常重要的,以避免在释放内存后使用悬空指针。
  • 资源管理:如果类管理动态分配的资源,赋值运算符应该正确地管理这些资源,避免内存泄漏和悬挂指针。
  • 返回值:赋值运算符应该返回当前对象的引用,这允许链式赋值,例如 a = b = c;

6. const成员函数

在C++中,const成员函数是指那些承诺不修改调用对象的数据成员的函数。当你声明一个成员函数为const时,你告诉编译器这个函数不会改变对象的任何成员变量(非静态成员变量)。这是通过在函数声明和定义后面加上const关键字来实现的。

class MyClass {
public:void normalFunction() {// 可以修改成员变量}void constFunction() const {// 不能修改成员变量}
};

 

注意事项

  • const成员函数内部,你不能修改任何非静态成员变量。
  • 你可以修改静态成员变量和局部变量,因为这些变量不与对象的状态直接相关。
  • 你可以在const成员函数内部调用其他非const成员函数,但前提是这些函数不修改任何非静态成员变量。

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

在C++中,你可以重载几种特殊的成员操作符,包括取地址操作符 & 和 const 取地址操作符 const &。虽然这些操作符通常不需要重载,因为编译器默认提供的版本就已经足够使用,但在某些特殊情况下,你可能需要自定义它们的行为。

重载取地址操作符 &

class MyClass {
public:// 重载取地址操作符MyClass* operator&() {// 返回当前对象的地址return this;}
};

重载const取地址操作符 const &

class MyClass {
public:// 重载const取地址操作符const MyClass* operator&() const {// 返回当前对象的const地址return this;}
};

注意事项

  • 重载取地址操作符通常不是一个好主意,因为这可能会导致混淆和意外的行为。通常,编译器提供的默认行为是正确的,即返回对象的实际地址。
  • 如果你确实重载了这些操作符,它们必须返回指向类类型的指针。对于 const 版本,返回类型应该是指向 const 类型的指针。
  • 重载这些操作符的返回类型不能是引用类型,因为地址操作符的预期行为是返回一个指针。
  • 重载这些操作符的目的是为了改变它们的行为,但通常不建议这样做,除非你有非常特殊的需求。

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

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

相关文章

单片机学习笔记 15. 串口通信(理论)

更多单片机学习笔记:单片机学习笔记 1. 点亮一个LED灯单片机学习笔记 2. LED灯闪烁单片机学习笔记 3. LED灯流水灯单片机学习笔记 4. 蜂鸣器滴~滴~滴~单片机学习笔记 5. 数码管静态显示单片机学习笔记 6. 数码管动态显示单片机学习笔记 7. 独立键盘单片机学习笔记 8…

vue获取yyyyMMddHHmmss格式的日期

文章目录 vue如何获取年月日时分秒的日期格式js获取yyyymmddhhmmss vue如何获取年月日时分秒的日期格式 在Vue中获取当前的年月日时分秒,可以使用JavaScript的Date对象。以下是一个简单的例子,展示了如何在Vue组件中获取并展示当前的日期和时间&#xf…

树莓派5+文心一言 -> 智能音箱

一、简介 效果:运行起来后,可以连续对话 硬件:树莓派5、麦克风、音箱,成本500-1000 软件:snowboy作为唤醒词、百度语音作为语音识别、brain作为指令匹配、百度文心一言作为对话模块、微软的edge-tts语音合成... 二…

SAP SD学习笔记17 - 投诉处理3 - Credit/Debit Memo依赖,Credit/Debit Memo

上一章讲了 请求书(发票)的取消。 SAP SD学习笔记16 - 请求书的取消 - VF11-CSDN博客 再往上几章,讲了下图里面的返品传票: SAP SD学习笔记14 - 投诉处理1 - 返品处理(退货处理)的流程以及系统实操&#…

Linux服务器使用JupyterLab

一、JupyterLab的配置 1. conda配置 自行搜索conda安装与配置。 2. 环境创建 (1)创建环境 conda create -n jupyter python3.10(2)激活环境 conda activate jupyter(3)安装jupyter包 pip install -i…

Flutter:页面滚动

1、单一页面,没有列表没分页的,推荐使用:SingleChildScrollView() return Scaffold(backgroundColor: Color(0xffF6F6F6),body: SingleChildScrollView(child: _buildView()) );2、列表没分页,如购物车页,每个item之间…

网络安全——浅谈HTTP协议

HTTP请求 HTTP请求是客户端往服务端发送请求动作,告知服务器自己的要求。 HTTP请求由状态行、请求头、请求正文三部分组成: 状态行:包括请求方式Method、资源路径URL、协议版本Version;请求头:包括一些访问的域名、…

Maya CurveBrush 笔刷开发

Maya CurveBrush 笔刷开发 | 智伤帝的个人博客 GitHub - FXTD-ODYSSEY/Maya-CurveBrush: Maya Tweak NUBRBS Curve Brush

使用GitZip for github插件下载git仓库中的单个文件

背景:git仓库不知道抽什么疯,下载不了单个文件,点击下载没有反应,遂找寻其他方法,在这里简单记录下。 使用GitZip for github插件下载仓库中的单个文件 1、首先在浏览器安装插件,并确保为打开状态。 2、然…

Vue 集成和使用 SQLite 的完整指东

1. 引言 SQLite 是一种轻量级的关系型数据库管理系统,以其简单易用、无需服务器等特点广泛应用于嵌入式系统、移动应用和小型应用程序中。在 Web 开发中,尤其是前端应用开发中,SQLite 可以作为客户端本地存储的一种选择,为用户提…

Python Flask框架入门指南

标题:Python Flask框架入门指南 摘要 Flask是一个轻量级的Web应用框架,用Python编写。它以其简洁的设计和强大的扩展性而闻名,非常适合快速开发小型到中型的应用程序。本文将介绍Flask的基本概念、安装步骤、核心功能以及一些实用示例&…

Unet改进57:在不同位置添加SFHF

本文内容:在不同位置添加CBAM注意力机制 论文简介 由于恶劣的大气条件或独特的降解机制,自然图像会遭受各种退化现象。这种多样性使得为各种恢复任务设计一个通用框架具有挑战性。现有的图像恢复方法没有探索不同退化现象之间的共性,而是侧重于在有限的恢复先验下对网络结构…

数据结构(初阶7)---七大排序法(堆排序,快速排序,归并排序,希尔排序,冒泡排序,选择排序,插入排序)(详解)

排序 1.插入排序2.希尔排序3.冒泡排序4.选择排序(双头排序优化版)5.堆排序6.快速排序1). 双指针法2).前后指针法3).非递归法 7.归并排序1).递归版本(递归的回退就是归并)2).非递归版本(迭代版本) 计算机执行的最多的操作之一就有排序,排序是一项极其重要的技能 接下…

DataWhale—PumpkinBook(TASK07支持向量机)

课程开源地址及相关视频链接:(当然这里也希望大家支持一下正版西瓜书和南瓜书图书,支持文睿、秦州等等致力于开源生态建设的大佬✿✿ヽ(▽)ノ✿) Datawhale-学用 AI,从此开始 【吃瓜教程】《机器学习公式详解》(南瓜…

【Python数据分析五十个小案例】使用自然语言处理(NLP)技术分析 Twitter 情感

博客主页:小馒头学python 本文专栏: Python爬虫五十个小案例 专栏简介:分享五十个Python爬虫小案例 项目简介 什么是情感分析 情感分析(Sentiment Analysis)是文本分析的一部分,旨在识别文本中传递的情感信息&…

【数据结构与算法】排序算法(上)——插入排序与选择排序

文章目录 一、常见的排序算法二、插入排序2.1、直接插入排序2.2、希尔排序( 缩小增量排序 ) 三、选择排序3.1、直接选择排序3.2、堆排序3.2.1、堆排序的代码实现 一、常见的排序算法 常见排序算法中有四大排序算法,第一是插入排序,二是选择排序&#xff…

Educator头歌:离散数学 - 图论

第1关&#xff1a;图的概念 任务描述 本关任务&#xff1a;学习图的基本概念&#xff0c;完成相关练习。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;图的概念。 图的概念 1.一个图G是一个有序三元组G<V,R,ϕ>&#xff0c;其中V是非空顶点集合&am…

OD E卷 - 实现 【虚拟理财游戏】

题目 在一款虚拟游戏中生活&#xff0c;必须进行投资以增强在虚拟游戏中的资产&#xff0c;避免被淘汰&#xff0c;现在有一家Bank&#xff0c;提供理财产品M个&#xff0c;风险及投资回报不同&#xff0c;你有N(元)进行投资&#xff0c;能接受的总风险值为X。你要在可接受范围…

oracle RAC各版本集群总结和常用命令汇总

oracle RAC学习 RAC介绍 RAC&#xff1a;高可用集群&#xff0c;负载均衡集群&#xff0c;高性能计算集群 RAC是⼀种⾼可⽤&#xff0c;⾼性能&#xff0c;负载均衡的share-everything的集群 8i:内存融合雏形 内存融合雏形&#xff08;Oracle Parallel Server&#xff09;…

数据资产管理是什么?为什么重要?核心组成部分(分类分级、登记追踪、质量管理、安全合规)、实施方法、未来趋势、战略意义

文章目录 一、引言&#xff1a;数据的新时代二、什么是数据资产管理&#xff1f;2.1 定义2.2 核心功能 三、为什么数据资产管理至关重要&#xff1f;3.1 面对的数据管理挑战 四、数据资产管理的核心组成部分4.1 数据分类与分级4.2 数据资产登记与追踪4.3 数据质量管理4.4 数据安…