c++之旅——第五弹

这篇具有很好参考价值的文章主要介绍了c++之旅——第五弹。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

大家好啊,这里是c++之旅第五弹,跟随我的步伐来开始这一篇的学习吧!

如果有知识性错误,欢迎各位指正!!一起加油!!

创作不易,希望大家多多支持哦!

c++之旅——第五弹,c++,开发语言

一,构造函数:

1.作用:

它是一种特殊的函数,主要用来在创建类对象时初始化对象,即为对象的成员变量赋初始值。(在构造函数中对类中的数据成员赋值 )

2.构造函数的定义:

(1)、构造函数名和类名相同

(2)、构造函数没有返回值类型和返回值

(3)、构造函数可以重载,需要满足函数重载的条件

3.构造函数的调用:

在定义一个类的对象时自动调用,也就是伴随对象产生同时调用做初始化操作

4.构造函数写法:

//不带参构造函数就是没有参数列表,函数体内操作和带参构造基本一致,只不过定义变量赋值时赋的是构造函数定义时写的默认值

类名(参数列表)//这里是带参构造
​
{
​
函数体;
​
//做在定义对象的时候想要做的事情,包括对数据成员赋值,当然构造函数除了对创建的对象进行初始化数据之外,还可以往里面写入类的成员函数的调用,用于在对象创建使就自动执行这个函数
​
}

具体写法示例:

class student
​
{
​
//属性举例:
​
int age;
​
char *pname;
​
public:
​
student()
​
{
​
}// 无参 ( 默认 )构造
​
student(int a)
​
{
​
}// 有参 ( 带参 )构造
​
}
​
//调用构造函数:
​
student stu1;// 调用默认构造
​
student stu2(1);// 调用带参构造

5.构造函数特点:

(1)、如果一个类中没有显式的给出构造函数,系统会自动地给出一个缺省的 ( 隐式 )什么都不干的构造函数

(2)、如果类中有多个构造函数,那么通常会有不同的参数列表和函数体(构造函数可以重载 )

(3)、如果用户提供了无参 ( 有参 ) 构造,那么系统就不再提供默认构造

(4) 、类中如果只有有参构造,没有无参构造,那么就不能调用默认构造的方式初始化对象,想用这种方式初始化对象那么就提供无参构造//基于第三点

(5)、构造函数需要写在公有访问属性下面,以便类外访问

6.构造函数注意点:

构造函数用来给类中成员数据赋初值,为什么不使用和结构体类似的直接赋值操作呢,这样只能在没有书写构造函数及所有数据是公有属性的情况下才能像结构变量一样直接赋初值。因为类中成员数据的属性默认是私有的(封装性),而如果通过这种方式来进行初始化就必须将成员数据属性改为public公有属性,所以一般不用这种直接初始化的操作而是使用构造函数来初始化类对象中的成员数据。

7.实际代码片段分析:

MyStu *pMs = new MyStu;//这是使用指针开辟空间时调用了无参构造函数的情况
delete pMs;
pMs = NULL;
MyStu *pMs2 = new MyStu(1245);//这是使用指针开辟空间时调用了有参构造函数的情况
delete pMs2;
pMs2= NULL;
MyStu mArr[2];//创建类对象数组,但是如果只在类中写有带参构造就不可使用

二,拷贝构造:

1.作用:

拷贝构造函数,它是一种特殊的构造函数,是在定义一个新的对象的时候用自身这种类型的对象来构造自身

2.拷贝构造函数的定义:

(1)、拷贝构造函数名和类名相同

(2)、拷贝构造函数没有返回值类型,和返回值

3.拷贝构造本质:

拷贝构造是有参构造的特殊形式,int b=20在C语言中是赋值,在c++中是拷贝构造(定义一个新的对象的时候用自身这种类型的对象来构造初始化自身)

4.拷贝构造注意事项:

(1)在C++里面结构和类没有太多区别,那么结构怎么算内存,类就怎么算(内存对齐)

(2)如果没有去书写拷贝构造,系统提供一个隐式的拷贝构造,可以理解为浅拷贝,浅拷贝只拷贝物理内存,不会拷贝逻辑内存,也就 是不会拷贝类中指针开辟的堆内存 如果类中的属性有指针,且会动态开辟,必须重写拷贝构造,去书写深拷贝(也就是自定义拷贝构造)

5.函数使用时本质上涉及到的拷贝:

函数调用过程可能发生两次拷贝,一次是实参到形参,一次是返回值时进行了拷贝,值是算出来的,但是返回时返回的是备份,备份值可以来到函数外面,原来算出的值直接在函数结束后丢弃

6.实际代码分析:

(1):

class CMyStu
{
    int id;
    char *pName;
public:
    CMyStu()
    {
        id = 0;
        pName = NULL;
    }
    CMyStu(int i,char *n)
    {
        id = i;
        int len = strlen(n);
        pName = new char[len + 1];
        strcpy(pName, n);
    }
    //自定义拷贝构造
    CMyStu(CMyStu const& other)//CMyStu(CMyStu m)会造成死循环
    {
        id = other.id;4
        pName = NULL;
        if (other.pName)
        {
            int len = strlen(other.pName);
            pName = new char[len + 1];
            strcpy(pName, other.pName);
        }
    }
    ~CMyStu()
    {
        if (pName)
            delete[] pName;
        pName = NULL;
    }
};

const作用:在C++中,拷贝构造函数用于创建一个对象的副本。通常情况下,拷贝构造函数的参数是一个引用类型,用于接收要拷贝的对象。在拷贝构造函数的参数引用前加上const关键字的作用是为了避免对被拷贝对象进行修改。 具体来说,将参数引用声明为const类型有以下几个原因:

  1. 避免修改被拷贝对象:通过将参数引用声明为const类型,可以确保在拷贝构造函数中不会对被拷贝对象进行任何修改。这是因为const修饰的引用只能读取对象的值,而不能修改它。

  2. 支持常量对象的拷贝:如果被拷贝对象是一个常量对象(const对象),则只能使用const引用来接收它,否则会导致编译错误。因此,将拷贝构造函数的参数引用声明为const类型,可以支持常量对象的拷贝。

(2):

CMyStu ms1 = ms;//拷贝构造的隐式调用(ms为已经定义好的类对象)
ms.~CMyStu();//析构函数是可以主动调用的,但是其清理效果只是相当于将类中的代码段复制过来,也就是只会实现清理开辟的堆内存,类的对象的其他项比如变量属性是不会清理掉的,所以一般不主动使用析构函数,而是在类对象生命周期到的时候自动调用
CMyStu ms2(ms);//拷贝构造的显式调用(相当于int a(10)这个意思)
CMyStu *pMs = new CMyStu(ms);//拷贝构造的显式调用(开辟一个堆内存时将内存赋为类对象ms)
delete pMs;
pMs=NULL;
CMyStu ms3;
ms3 = ms;//这个不是拷贝构造,是赋值,因为构造是对象产生内存之后立马给值,不是立马给值的就是赋值操作

二,析构函数:析构函数和构造函数一样,也是一种特殊的函数,主要的作用是在对象结束生命周期时,系统自动调用析构函数,来做一些清理工作

1.析构函数的定义:

(1)、函数名与类名相同,在前面加上一个~

~类名(){}

(2)、没有返回值类型和返回值,也没有参数

(3)、如果类中没有自己写析构函数,那么系统将会给出一个隐式什么都不干的析构函数

2.析构函数的调用:

(1)、通过类对象主动调用(和类中普通函数的使用方式一致,也就是用对象加‘.'使用的,这和结构体是一致的)

(2)、对象死亡时,析构函数被自动调用

3.析构函数的特点:

(1)、析构函数是对对象做一些清理工作,主动调用析构函数,不意味对象死亡

(2)、一个类只有一个析构函数

(3)、析构函数需要写在公有下面

(4) 、析构函数里面的代码可以理解为是当对象死亡时要执行的代码

4.注意事项:

(1)如果一个类中有了指针来指向堆内存,那么析构函数就必须要自己重写,不能不写来使用默认的什么都不干的析构函数,否则会造成内存泄漏,积累下去会导致堆区内存越来越小

(2)由于拷贝构造和析构函数的特点,我们在对象有开辟堆内存的时候才需要手写拷贝构造和析构函数

三,this指针:系统自动生成且隐藏的指针,只能在类中使用,该指针总是指向调用者对象

1.理解方式:this指针理解为一个只能在类中的指针,指向当前对象的指针。在类中:this->成员;(*this).成员

2.实际代码分析:

#include <string.h>
class CMyStu
{
    int id;
    char *pName;
public:
    CMyStu()
    {
        id = 0;
        pName = NULL;
    }
    CMyStu(int id, char *pName)//this指针可以区分同名
    {
        this->id = id;
        int len = strlen(pName);
        this->pName = new char[len + 1];
        strcpy(this->pName, pName);
    }
    ~CMyStu()
    {
        if (pName)
            delete[]pName;
        pName = NULL;
    }
    CMyStu& operator =(CMyStu const& destStu)
        //返回值为什么使用的是引用类型,因为是返回自己,所以没有必要再将自己拷贝一份给到返回值,使用引用类型直接返回自己本身
    {
        id = destStu.id;
        pName = NULL;
        if (destStu.pName)
        {
            int len = strlen(destStu.pName);
            pName = new char[len + 1];
            strcpy(pName, destStu.pName);
        }
        return *this;//在调用者自己的成员函数中返回调用者自己
    }
};

用于区分同名不常用,一般是用于返回对象的,原理类似于赋值表达式的值是被赋值变量的值,eg:if(a=0),里面表达式值就是0

 文章来源地址https://www.toymoban.com/news/detail-839787.html

到了这里,关于c++之旅——第五弹的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Kafka入门到实战-第五弹

    声明: 由于操作系统, 版本更新等原因, 文章所列内容不一定100%复现, 还要以官方信息为准 Apache Kafka 是一个开源的分布式事件流平台,提供高性能数据管道、流分析、 数据集成和任务关键型应用程序。 本节将在Kafka集群上执行。所有工具都可以在Kafka发行版的bin/目录下使用,

    2024年04月15日
    浏览(40)
  • 力扣刷MySQL-第五弹(详细讲解)

     🎉欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克🍹 ✨博客主页:小小恶斯法克的博客 🎈该系列文章专栏:力扣刷题讲解-MySQL 🍹文章作者技术和水平很有限,如果文中出现错误,希望大家能指正🙏 📜 感谢大家的关注! ❤️ 目录 🚀寻找用

    2024年01月22日
    浏览(43)
  • Android11编译第五弹:开启VPN权限

    问题:智能货柜上线以后,因为分布在全国各地,或者在国外,遇到问题需要调试设备的时候,需要及时连接设备,查看设备信息,拉取日志。 一种方式是直接上传日志到云端,通过云端查看日志信息,但是耗费流量,而且浪费云端资源; 二种方式:采用VPN网络,通过adb

    2024年02月09日
    浏览(40)
  • 深入理解数据结构第五弹——排序(2)——快速排序

    排序(1): 深入了解数据结构第四弹——排序(1)——插入排序和希尔排序-CSDN博客 前言: 在前面我们已经讲过了几种排序方式,他们的效率有快有慢,今天我们来学习一种非常高效的排序方式——快速排序 目录 一、快速排序的思想 二、快速排序的递归实现 2.1 霍尔法

    2024年04月15日
    浏览(48)
  • web爬虫第五弹 - JS逆向入门(猿人学第一题)

    0- 前言 爬虫是一门需要实战的学问。 而对于初学者来说,要想学好反爬,js逆向则是敲门砖。今天给大家带来一个js逆向入门实例,接下来我们一步一步来感受下入门的逆向是什么样的。该案例选自猿人学练习题。猿人学第一题 1- 拿到需求 进入页面拿到需求我们先不要急着

    2024年02月14日
    浏览(38)
  • 互联网Java工程师面试题·Java 并发编程篇·第五弹

    目录 52、什么是线程池? 为什么要使用它? 53、怎么检测一个线程是否拥有锁? 54、你如何在 Java 中获取线程堆栈? 55、JVM 中哪个参数是用来控制线程的栈堆栈小的? 56、Thread 类中的 yield 方法有什么作用? 57、Java 中 ConcurrentHashMap 的并发度是什么? 58、Java 中 Semaphore 是什么

    2024年02月07日
    浏览(67)
  • k8s控制器之DaemonSet--第五弹更新 DaemonSet

    DaemonSet 有两种更新策略: OnDelete : 使用 OnDelete 更新策略时,在更新 DaemonSet 模板后,只有当你手动删除老的 DaemonSet pods 之后,新的 DaemonSet Pod 才会 被自动创建。跟 Kubernetes 1.6 以前的版本类似。 RollingUpdate : 这是默认的更新策略。使用 RollingUpdate 更新策略时,在更新 DaemonSe

    2024年02月11日
    浏览(40)
  • k8s服务发现之第五弹--使用 Service 连接到应用

    通过前面教程的学习,我们已经可以将容器化的应用程序在 Kubernetes 中运行起来,并且发布到 Kubernetes 内/外的网络上。 通常,Docker 使用一种 host-private 的联网方式,在此情况下,只有两个容器都在同一个节点(主机)上时,一个容器才可以通过网络连接另一个容器。为了使

    2024年02月15日
    浏览(41)
  • k8s控制器之job--第五弹Job的自动清理

    系统中已经完成的 Job 通常是不在需要里的,长期在系统中保留这些对象,将给 apiserver 带来很大的压力。如果通过更高级别的控制器(例如 CronJobs)来管理 Job,则 CronJob 可以根据其中定义的基于容量的清理策略(capacity-based cleanup policy)自动清理Job。 除了 CronJob 之外,TTL 机

    2024年02月11日
    浏览(44)
  • C++语言程序设计第五版 - 郑莉(第六章课后习题)

    6-20 实现一个名为 SimpleCircle 的简单圆类。其数据成员 int* itsRadius 为一个指向其半径值的指针,存放其半径值。设计对数据成员的各种操作,给出这个类的完整实现并测试这个类。 6-21 编写一个函数,统计一条英文句子中字母的个数,在主程序中实现输入输出。 6-22 编写函数

    2023年04月25日
    浏览(63)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包