类和对象提高

此篇继续讲解类和对象的提高知识,包括默认成员函数、运算符重载等相关内容,没有看过 C++基础知识类和对象基础知识(可翻阅我的文章)的小伙伴,可以先收藏,之后学习完再看效果会更好哦。

默认成员函数

在一个空类中并不是什么都没有,编译器会调用六个默认成员函数

在这里插入图片描述

1)构造函数

我们常常会忘记调用Init函数,导致没有初始化,而如果使用构造函数初始化就不会出现这种现象,因为编译器会自动调用。怎么样,体会到 C++ 的快乐了吧。

注意:构造函数不是开空间创建对象,而是初始化对象

【特性】

  1. 函数名和类名相同,且无返回值
  2. 对象实例化时编译器自动调用
  3. 可以重载

【实例对比】

①老版本

class Date
{
public:void Init(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 d1;d1.Init(2024, 2, 26);d1.Print();// 弊端就是会忘记Initreturn 0;
}

②新版本

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(2024, 2, 26); // 调用带参的构造函数//Date d3(); //错误,此处是为了避免跟函数声明混淆
}

【注意】:如果显式调用,编译器就不会生成,否则会生成无参的默认构造函数(注意和默认成员函数区分)

PS:无参构造函数、全缺省构造函数、我们没写编译器默认生成的构造函数,都可以认为是默认构造函数,并且默认构造函数只能有一个

Q:有小伙伴觉得这个系统调用的默认构造有什么用?对象的成员变量不还是随机值吗?

对于内置类型(语言提供的数据类型,eg. int/char)不作处理,在C++11中可以在类声明时给默认值;而对于自定义类型(eg. class/struct/union),会去调用各自的构造函数,如果不具备对应的默认构造函数则会报错。


2)析构函数

同样的,Destroy也是经常容易忘记的操作,而在C++中,引入析构函数来实现自动清理对象中的资源(妈妈再也不用担心我会忘记Destroy了)

注意:不是对对象本身的销毁,销毁工作是由编译器完成的,析构的作用是在销毁时完成对象中资源的清理工作。

跟构造函数类似,对于每个成员变量,内置类型最后系统会将其内存回收,而自定义类型需要调用它的析构函数。

【示例】

#include<iostream>
using namespace std;typedef int DataType;
class Stack
{
public:Stack(size_t capacity = 3){// 有资源申请_array = (DataType*)malloc(sizeof(DataType) * capacity);if (NULL == _array){perror("malloc申请空间失败!");return; }_capacity = capacity;_size = 0; }void Push(DataType data){_array[_size] = data;_size++; }// ~类名() 这种表达方式为析构函数~Stack() {if (_array) {free(_array);_array = NULL;_capacity = 0;_size = 0;} }
private:DataType* _array;int _capacity;int _size;
};void TestStack()
{Stack s;s.Push(1);s.Push(2);
}

【注意】

(1) 如果类中没有申请资源时,析构函数可以不写,直接使用编译器生成的默认析构函数,比如 Date类;

有资源申请时,一定要写,否则会造成资源泄漏,比如上面的Stack类。

(2)后定义的先析构;

析构顺序:局部对象(后定义先析构) → 局部静态 → 全局变量(后定义先析构)

(3)析构函数不能重载


3)拷贝构造函数

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

【示例】

class Date
{
public:// 拷贝构造,是构造函数的一个重载形式Date(const Date& d){_year = d._year;_month = d._month;_day = d._day;}Date(int year, int month, int day){_year = year;_month = month;_day = day;}private:int _year;int _month;int _day;
};void TestDate()
{Date d1(2024, 2, 26); Date d2(d1);  // 拷贝构造
}

【注意】

(1)拷贝构造的参数只能是类对象的引用,否则会引发无穷递归。因为在传值传参的时候,会形成一个新的拷贝构造,然后就再调用拷贝构造,无穷递归下去了。

(2)并且是const类的,避免对原先的对象作出修改。
(3)如果没有显式定义,编译器会生成默认的拷贝构造函数,其中的内置类型成员按内存存储的字节序拷贝,自定义类型成员会调用它的拷贝构造,这个过程称为浅拷贝或值拷贝。

【重点】

一般来说,如果没有涉及资源申请(动态内存开辟),拷贝构造可写可不写,但是一旦涉及资源申请就必须写了。

如果不写拷贝构造,会调用默认的拷贝构造,则会将原对象的内容按值拷贝,其中的指针会指向同一块空间

而在销毁时,其中一个对象已经释放对应地址的空间,而后释放的对象会对相同的位置进行释放,导致程序崩溃。


4)赋值运算符重载

引入:C++为了自定义类型也可以像内置类型那样使用运算操作符,增强代码的可读性,引入了运算符重载,运算符重载是具有特殊函数名的函数。

使用方式:返回值类型 operator操作符(参数列表)

【注意事项】

  1. 不能创造新的操作符,例如operator@
  2. 内置类型的运算符不可改变含义
  3. .* :: sizeof ?: . 这五个运算符不可重载

【示例】以日期类的小于和等于符号作例子

bool Date::operator==(const Date& d)
{return _year == d._year&& _month == d._month&& _day == d._day;
}bool Date::operator<(const Date& d)
{if (_year < d._year){return true;}else if (_year == d._year){if (_month < d._month)return true;else if (_month == d._month){if (_day < d._day)return true;}}return false;
}

其实在实现了这两个运算符重载之后,其他的就可以复用已经重载过的了

bool Date::operator<=(const Date& d) 
{return *this < d || * this == d;
}
// 是不是很爽bool Date::operator>(const Date& d)
{return !(*this <= d);
}bool Date::operator>=(const Date& d)
{return !(*this < d);
}bool Date::operator!=(const Date& d)
{return !(*this == d);
}

赋值运算符重载是一种特殊的运算符重载,属于默认成员函数,也就是说不显式写,编译器也会自动调用。与拷贝构造类似,当没有涉及资源配置时,可写可不写,但如果涉及资源配置必须写

【示例】

Date& operator=(const Date& d)
{if (this != &d){_year = d._year;_month = d._month;_day = d._day;}return *this;
}

【注意点】

  1. 参数是本类对象的引用
  2. 赋值运算符只能重载成类的成员函数不能重载成全局函数,因为赋值运算符如果不显式实现,编译器会生成一个默认的,全局的赋值重载和编译器在类中生成的默认赋值重载冲突了。
  3. 拷贝构造是用一个已经存在的对象去初始化一个新的对象,而赋值运算符重载是两个已经存在的对象进行赋值操作。

关于日期类的运算符重载我会单独写一篇博客详解,敬请期待!

在这里插入图片描述


5)取地址操作符重载

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

这两个一般不需要重载,用编译器自动调用的就好,所以不用深入学习。

如果对你有帮助的话,不妨点个赞鼓励一下博主~

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

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

相关文章

力扣 第 387 场周赛 解题报告 | 珂学家 | 离散化树状数组 + 模拟场

前言 整体评价 手速场模拟场&#xff0c;思路和解法都蛮直接的。 所以搞点活 如果T2&#xff0c;如果不固定左上角&#xff0c;批量查询某个点为左上角&#xff0c;求满足总和 ≤ k \le k ≤k的子矩阵个数 如果T2&#xff0c;如果不固定左上角&#xff0c;求总和 ≤ k \le k…

老年人居家安全问题,全视通社区居家养老解决方案来赋能

近年来&#xff0c;老年人居家环境问题逐渐受到社会的关注。从新闻报道得知&#xff0c;传统居家环境对老年人存在诸多挑战&#xff0c;比如在入户空间、起居&#xff08;室&#xff09;厅、卧室、卫生间、厨房等区域。这些挑战不仅影响老年人的生活质量&#xff0c;还可能导致…

【大厂AI课学习笔记NO.60】(13)模型泛化性的评价

我们学习了过拟合和欠拟合&#xff0c;具体见我的文章&#xff1a;https://giszz.blog.csdn.net/article/details/136440338 那么今天&#xff0c;我们来学习模型泛化性的评价。 泛化性的问题&#xff0c;我们也讨论过了&#xff0c;那么如何评价模型的泛化性呢&#xff1f; …

vue 常用的 UI 组件库之一:Vuetify组件库

Vuetify是一个基于Vue.js 的Material Design组件库&#xff0c;它提供了一套完整的、预构建的、可自定义的、响应式的组件&#xff0c;以便开发者可以快速构建美观且功能强大的Web应用程序。Vuetify遵循Material Design设计指南&#xff0c;提供了一系列易于使用的组件&#xf…

[项目设计] 从零实现的高并发内存池(二)

&#x1f308; 博客个人主页&#xff1a;Chris在Coding &#x1f3a5; 本文所属专栏&#xff1a;[高并发内存池] ❤️ 前置学习专栏&#xff1a;[Linux学习] ⏰ 我们仍在旅途 ​ 目录 2.高并发内存池整体架构 3.ThreadCache实现 3.1 ThreadCache整体架构…

这是开玩笑吗?加个工具,WPS与Excel表格变成了应用系统

表格处理数据简单快捷&#xff0c;是个人用户的首选。然而&#xff0c;当企业长期使用&#xff0c;成本表、客户表、销售表等堆积如山&#xff0c;寻找所需表格如同大海捞针&#xff0c;稍有不慎便可能导致数据丢失、混乱。即便使用WPS和Excel这样的表格软件&#xff0c;处理大…

Harmony OS 父子组件传参

Harmony OS 父子组件传参案例 一、Prop&#xff1a;从父组件单向同步状态 类似于vue的prop传参&#xff0c;只能父组件传参给子组件 当点击父组件的按钮时&#xff0c;改变message值&#xff0c;参数跟着更新。并且子组件也跟着更新&#xff08;前提是要子组件加上prop装饰器…

力扣hot100:1.两数之和

输入中可能存在重复值 。 分析&#xff1a; 本题需要返回的是数组下标&#xff0c;因此如果需要使用排序然后双指针的话&#xff0c;需要用到哈希表&#xff0c;但是由于输入中可能存在重复值&#xff0c;因此哈希表的value值必须是vector<int>。 使用双指针求目标值targ…

Ansible setup 模块 该模块主要用于收集信息,是通过调用facts组件来实现的。

目录 作用查看信息验证保存信息验证 作用 该模块主要用于收集信息&#xff0c;是通过调用facts组件来实现的。   facts组件是Ansible用于采集被管机器设备信息的一个功能&#xff0c;我们可以使用setup模块查机器的所有facts信息&#xff0c;可以使用filter来查看指定信息。…

【系统维护】-微软电脑管家官网

以前没注意&#xff0c;最近一次升级后给安装了微软电脑管家&#xff0c;特别是瘦身功能感觉比较好&#xff0c;以前总是装第三方或者用命令行情况&#xff0c;有时候不小心还会给系统搞崩溃。感觉这个会安全很多。 还有其他一些功能&#xff0c;建议感兴趣的的可以试一下&…

Axure导入使用ElementUI组件库

在使用Axure进行UI设计时&#xff0c;我们可能导入ElementUI组件库或者一些其他的元件库&#xff0c;其实非常简单&#xff0c;如果你还没有装好Axure可以先安装好AxureRP9汉化版&#xff0c;接下来&#xff0c;我们以AxureRP9汉化版来演示如何导入ElementUI组件库。 第一步&a…

CMake 生成器

关于 CMake 的讨论已有不少&#xff0c;因为 CMake 无疑是一个伟大的工具。如果你搜索“CMake”&#xff0c;你肯定会看到这样一句话&#xff1a;“CMake 不是一个构建系统&#xff0c;而是一个构建系统生成器”。因此&#xff0c;本篇文章的内容主要围绕什么是 CMake 生成器&a…