首页 > 编程语言 >C++-类和对象(3)

C++-类和对象(3)

时间:2023-09-14 23:33:36浏览次数:26  
标签:函数 对象 C++ 编译器 析构 拷贝 构造函数

今天,继续和大家分享与类和对象相关的知识,本次文章的内容主要分享拷贝构造函数相关的知识。

在学习拷贝构造函数之前,我们先对构造函数和析构函数进行一个总结回顾,在接这往下。

构造函数和析构函数的总结回顾

不论是构造函数还析构函数,我们只需要抓它们的特性,就可以很好的使用它们了。

构造函数

构造函数的特性有七个:

1.函数名与类名相同

2.无返回值

3.构造函数可以重载

4.对象实例化时编译器会自动调用

5.若没有显示写构造函数,编译器会自动生成一个默认构造函数

6.编译器生成的默认构造函数,对于内置类型,有些会进行初始化,有些不会,并没有明确的规定,为此C++11打了个补丁,内置类型在类中的声明时可以给默认值。对于自定义类型会调用它的默认构造函数。

7.不论是无参的构造函数,全给缺省值的构造函数,还是编译器自动生成的默认构造函数,都称之为构造函数。

根据这些特性,可以得出:

1.一般情况下,我们需要写自己写构造函数。

2.在一个类中,内置类型成员给了默认值,自定义类型成员,有自己的默认构造函数了。我们就可以不用写构造函数了。就比如说下面这种情况的类queue

C++-类和对象(3)_拷贝构造函数

析构函数

析构函数的特性有四个:

1.函数名由波浪号和类名组成

2.析构函数只能有一个,不能重载

3.无返回值

4.若不显示写析构函数,编译器会自动生成一个

对于析构函数,如果没有动态申请空间的资源,可以不用写析构函数,直接使用编译器生成的就行了。像日期类就不用。

C++-类和对象(3)_构造函数_02

还有就是,如果你的成员变量都是自定义类型也不需要写析构函数,因为自定义类型都会调取自己相应的析构函数进行析构。

接下来,我们进入本次的主要内容的讲解。

拷贝构造函数

有时候,我们需要对某些数据进行访问操作,但又需要保护好原数据不丢失。我们通常会进行拷贝一份。C++规定数据的拷贝必须调用相应的拷贝构造函数来进行拷贝。那拷贝构造函数如何定义实现呢?它的定义方式与构造函数有一些类似,也是以类名作为函数名。这里我们以日期类为例,进行演示。

C++-类和对象(3)_构造函数_03

首先,我们以类名作为函数名,然后,完成实现。注意,在定义这个拷贝函数时,不能像43行那样定义传值调用,否则会陷入无限的递归死循环。这是什么原因呢?因为当我们调用拷贝构造函数时,传值给形参d,这里会发生对象的拷贝,而对象的拷贝又会调用拷贝构造函数,就这样一环套一环,一直调用拷贝构造函数,直到栈溢出,程序崩溃。

C++-类和对象(3)_构造函数_04

拷贝构造函数的定义实现我们已经完成了,来看一下效果。

C++-类和对象(3)_析构函数_05

我们先定义一个变量d1,它的日期是2023.9.14,紧接着,我们再以它为拷贝的对象创建对象d2。

C++-类和对象(3)_构造函数_06

从监视窗口,我们可以看到对象d2已经完成了对象d1的拷贝。我们把拷贝函数注释掉看看效果。

C++-类和对象(3)_拷贝构造函数_07

从监视窗口中,我们可以发现,即使没有拷贝构造函数,编译器也能完成拷贝的工作,那我们还需要拷贝构造函数做什么呢?

我们以没有写拷贝函数的栈为例:

C++-类和对象(3)_构造函数_08

C++-类和对象(3)_析构函数_09

同样的,我们先定义一个栈s1,然后,以s1为拷贝对象创建对象s2。然后,我们运行一下程序来看看效果。

C++-类和对象(3)_析构函数_10

程序中止了,这是什么原因呢?

C++-类和对象(3)_拷贝构造函数_11

这是由于编译器生成的拷贝构造函数,为浅拷贝。从监视窗口看,我们不难发现,对象s1和对象s2的_arr的地址是一样的,也就是它们指向同一块空间

C++-类和对象(3)_构造函数_12

当程序结束时,两个对象都会进行析构,这样一来就对同一个空间析构了两次了。一段空间怎么能析构两次,这显然是荒谬的,于是程序就终止了。

像栈这些自己开辟空间储存数据的结构,我们不能依赖编译器自动生成的拷贝构造函数,我们需要自己写一个拷贝函数,进行深拷贝,为新的对象开辟一段新的空间来存放数据,避免两个对象指向同一段空间的现象出现。

以上是拷贝构造函数的主要用途所在,接下来,我们对它的特征进行总结一下:

1.拷贝构造函数是构造函数的一个重载形式。

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

3.若为显示定义拷贝构造函数,编译器会自动生成一个默认拷贝构造函数。默认拷贝构造函数会根据对象的内存大小完成拷贝,这种拷贝成为浅拷贝。

好了,到这里,我们本次的分享就到此结束了,不知道我有没有说明白,给予你一点点收获。如果你有所收获,别忘了给我点个赞,这是对我最好的回馈,当然你也可以在评论发表一下你的收获和心得,亦或者指出我的不足之处。如果喜欢我的分享,别忘了给我点关注噢。

标签:函数,对象,C++,编译器,析构,拷贝,构造函数
From: https://blog.51cto.com/u_15933803/7475365

相关文章

  • Vue-选择器v-model绑定对象
    Vue-选择器v-model绑定对象<template><el-selectv-model="value"placeholder="请选择"><el-optionv-for="iteminoptions":key="item.value":label="item.label":value=&quo......
  • C++下标运算符详解
    C++规定,下标运算符[]必须以成员函数的形式进行重载。该重载函数在类中的声明格式如下:返回值类型&operator[](参数);const返回值类型&operator[](参数)const;使用第一种声明方式,[]不仅可以访问元素,还可以修改元素。使用第二种声明方式,[]只能访问而不能修改元素。在实......
  • C# 对象比较
    1.ReferenceEquals(object o1, object o2):静态方法:比较两个对象的引用,引用相同返回true,否则返回false,同为null是返回true;ReferenceEquals进行值类型比较时总是返回false,因为两个值类型需要分别装箱到对象中,是不同的引用 ;从名称中便可知它用来比较两者是否是相同的引用,我们......
  • C++ STL
    Dev-C++可在工具->编译选项->代码生成/优化->代码生成->语言标准中选择“ISOC++11”或“GNUC++11”来支持C++11的新特性(蓝Dev还不支持C++14)不声明下,区间均为左闭右开区间,typename表示一个数据类型而不是C++的关键字。Containter(容器)vectorvector<t......
  • C++字符串
      1,2这个形式的字符串数组,就和普通数组一样,定义后面的大括号,里面装着每个具体的值,然后3,4直接表示出来,然后其实直接3就OK了,4可能是为了方便看。   字符串数组输入部分1.这个。。先把字符串数组定义好,然后使用cin直接输入进去2.如果想要读入包含空格键之类字符串的话......
  • C++11之智能指针(万字长文详解)
    C++11之智能指针为什么需要智能指针#include<iostream>usingnamespacestd;intdiv(){inta,b;cin>>a>>b;if(b==0)throwinvalid_argument("除0错误");returna/b;}voidFunc(){//1、如果p1这......
  • C++基础语言作用
    C++跟C语言是相关联的。页面排序:includeincludeusingnamespacestd;intmain(){...return0;}cin作为输入,类似于C语言的scanf。输入时添加>>a代表输入a值。可以接收一行内多个数据输入,不可以接收多行数据。cout作为输出,类似C语言的printf。cout默认是在一行内输出,如......
  • ros2迁移c++之package.xml、CMakeLists.txt及编译
    1、package.xml<package><!--1.根标签--> <name><!--2.包名--> <version><!--3.版本号--> <description><!--4.包描述--> <maintainer><!--5.维护者--> <......
  • c++并发编程实战-第3章 在线程间共享数据
    线程间共享数据的问题多线程之间共享数据,最大的问题便是数据竞争导致的异常问题。多个线程操作同一块资源,如果不做任何限制,那么一定会发生错误。例如:1intg_nResource=0;2voidthread_entry()3{4for(inti=0;i<10000000;++i)5g_nResource++......
  • Java从入门到精通-类和对象(三)
    1.6实践与练习1.1面向对象概述基础练习题:1.创建一个类Person,具有姓名和年龄两个成员变量,以及一个方法displayInfo()用于显示姓名和年龄。然后创建一个Person对象并调用displayInfo()方法。publicclassPerson{//成员变量privateStringname;privateintage;......