C++类和对象:构造函数,析构函数,拷贝构造

embedded/2024/9/24 21:17:10/

文章目录

    • 1.类的6个默认成员函数
    • 2. 构造函数
      • 2.1 概念
      • 2.2 特性
    • 3.析构函数
      • 3.1 概念
      • 3.2 特性
    • 4.拷贝构造

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

一个类中什么都不写,就是空类。而空类实际上有成员,当一个类中什么都不写时,编译器会生成六个对应默认成员函数。

默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数。
在这里插入图片描述
本文先介绍前三个:构造函数,析构函数,拷贝构造

2. 构造函数

2.1 概念

构造函数是一个特殊的成员函数名字与类名相同,创建类类型对象时由编译器自动调用,并且在对象整个生命周期内只调用一次

如有以下Date类:

class Date
{
public:Date(){cout << "调用了构造函数" << endl;_year = 1;_month = 1;_day = 1;}void Print(){cout << _year << "-" << _month << "-" << _day << endl;}int _year;int _month;int _day;
};int main()
{Date test;cout << test._day << " " << test._month << " " << test._year << endl;return 0;
}

在这里插入图片描述

Date的对象实例化时,会自动且必须调用构造函数,这里Date的构造函数是使类的属性初始化。

2.2 特性

构造函数是特殊的成员函数,需要注意的是,构造函数虽然名称叫构造,但是构造函数的主要任务并不是开空间创建对象,而是初始化对象

特征!

  1. 函数名与类名相同。
  2. 无返回值。
  3. 对象实例化时编译器自动调用对应的构造函数。
  4. 构造函数可以重载,可以多写几个,定义多种初始化方式
//构造函数重载
#include <iostream>
using namespace std;class Date
{
public:Date(){cout << "调用了无参构造函数" << endl;}Date(int x){cout << "调用了有参构造函数" << endl;}
private:int _year;int _month;int _day;
};int main()
{Date test;//调用了无参构造函数Date test1(10);//调用了有参构造函数return 0;
}
  1. 如果类中没有显式定义构造函数,则C++编译器会自动生成一个无参的默认构造函数,这个自动生成的默认构造函数一般不会做任何事(不同的编译器不太一样),一旦用户显式定义编译器将不再生成
class Date
{
public:private:int _year;int _month;int _day;
};
int main()
{//程序正常运行,因为编译器自动生成无参的构造函数,示例化会使用这个构造函数Date d1;return 0;
}
class Date
{
public:Date(int year, int month, int day){_year = year;_month = month;_day = day;}
private:int _year;int _month;int _day;
};
int main()
{// 1. 用户显式定义了构造函数,编译器不会生成默认构造函数// 2. 程序不能通过编译,实例化没有适合的构造函数调用Date d1;return 0;
}
  1. C++11 中针对内置类型成员不初始化的缺陷,又打了补丁,即:内置类型成员变量在类中声明时可以给默认值。
class Date
{
private:int _year = 1;int _month = 1;int _day = 1 ;
};
int main()
{Date d1;return 0;
}
  1. 如果类中有自定义类型,那么在实例化时会调用自定义类型的构造函数
class Time
{
public:Time(){cout << "Time()" << endl;_hour = 0;_minute = 0;_second = 0;}
private:int _hour;int _minute;int _second;
};
class Date
{
private:// 基本类型(内置类型)int _year;int _month;int _day;// 自定义类型Time _t;
};
int main()
{Date d;return 0;
}
  1. 无参的构造函数和全缺省的构造函数都称为默认构造函数,并且默认构造函数只能有一个。注意:无参构造函数全缺省构造函数编译器默认生成的构造函数都可以认为是默认构造函数。总结:不传参数就可以调用的就是默认构造

3.析构函数

3.1 概念

析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。

3.2 特性

  1. 析构函数名是在类名前加上字符 ~
  2. 无参数无返回值类型
  3. 一个类只能有一个析构函数。若未显式定义,系统会自动生成默认的析构函数。注意:析构函数不能重载
  4. 对象生命周期结束时,C++编译系统系统自动调用析构函数。并且在同一作用域下,如果有多个类实例化,那么析构函数的调用顺序与构造函数完全相反,这句话用以下代码具体说明:
class A
{
public:A(){cout << "调用了A的析构函数" << endl;};~A(){cout << "调用了A的析构函数" << endl;}
};
class B
{
public:B(){cout << "调用了B的析构函数" << endl;};~B(){cout << "调用了B的析构函数" << endl;}
};
class C
{
public:C(){cout << "调用了C的析构函数" << endl;};~C(){cout << "调用了C的析构函数" << endl;}
};
int main()
{A test1;cout << "----------------" << endl;B test2;cout << "----------------" << endl;C test3;cout << "----------------" << endl;return 0;
}

在这里插入图片描述
可以看到程序运行到最后时,A B C 类开始调用他们的析构函数,调用顺序与构造函数完全相反。

  1. 与构造函数类似,默认析构函数对于内置类型不做处理,对于自定义类型会去调用其的析构函数。
  2. 实践中总结:有资源要清理,就写析构。如Stack类。没有资源要清理(如Date类),或者没有内置类型只剩下自定义类型(如MyQueue),用默认生成的析构就可以了。
    在这里插入图片描述

4.拷贝构造

拷贝构造也是一种构造函数,但其构造的形式是以拷贝的方式进行。

  1. 拷贝构造函数是构造函数的一个重载形式
  2. 拷贝构造函数的参数只有一个且必须是该类型对象的引用(Date类举个例子)
class Date
{
public://默认构造函数Date(){_year = 1;_month = 1;_day = 1;}//拷贝构造Date(Date& test){_year = test._year;_month = test._month;_day = test._day;}
private:int _year;int _month;int _day;
};

为什么拷贝构造的参数是引用而不是直接传参呢?我们需要了解传自定义类型参数的实质,如果直接传值:

//Date类内
...
Date(Date test)
{_year = test._year;_month = test._month;_day = test._day;
}
...
//main
Date a1;
Date a2(a1);

在这里插入图片描述
同时说明:传入自定义类型作为参数(参数非引用)时,是又创建了个临时类,再调用这个临时类拷贝构造,以你传入的参数作为拷贝构造的参数的。结论:以类为参数的函数,在执行函数时,会调用一次类的拷贝构造

  1. 若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按
    字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。
class Date
{
public://默认构造函数Date(){_year = 1;_month = 1;_day = 1;}//不显示定义拷贝构造 
private:int _year;int _month;int _day;
};int main()
{Date t1;Date t2(t1);//使用默认拷贝构造可以实现浅拷贝
}
  1. 类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请
    时,则拷贝构造函数是一定要写的
    ,否则就是浅拷贝。
class Date
{
public:Date(){arr = (int*)malloc(20);_year = 1;_month = 1;_day = 1;}~Date(){free(arr);}
private:int _year;int _month;int _day;int* arr;
};int main()
{Date t1;//使用默认的拷贝构造,是浅拷贝,t1与t2的arr指针指向同一片空间Date t2(t1); //t1与t2最后都调用析构函数,程序崩溃 同一片空间free了两次return 0;
}

在这里插入图片描述
5. 拷贝构造函数典型调用场景:

  • 使用已存在对象创建新对象
  • 函数参数类型为类的类型对象
  • 函数返回值类型为类的类型对象
class Date
{
public:Date(int year, int minute, int day){cout << "Date(int,int,int):" << this << endl;}Date(const Date& d){cout << "Date(const Date& d):" << this << endl;}~Date(){cout << "~Date():" << this << endl;}
private:int _year;int _month;int _day;
};
Date Test(Date d)
{Date temp(d);return temp;
}
int main()
{Date d1(2022, 1, 13);Test(d1);return 0;
}

在这里插入图片描述
为了提高程序效率,一般对象传参时,尽量使用引用类型,返回时根据实际场景,能用引用
尽量使用引用。


http://www.ppmy.cn/embedded/2124.html

相关文章

医学访问学者专栏-申请条件及类别

在国外访问学者申请中&#xff0c;医学领域的研究、教学及从业人员占有相当大的比例&#xff0c;这些医学访问学者都有哪些申请条件及类别&#xff1f;本文知识人网小编就相关问题进行详细阐述&#xff0c;并附带案例说明。 一、医学访问学者的职业发展前景如何&#xff1f; 1…

负载均衡的原理及算法

负载均衡&#xff08;Load Balancing&#xff09;是指在计算机网络中将工作负载&#xff08;如请求、数据流量等&#xff09;分配给多个计算资源&#xff08;如服务器、网络连接等&#xff09;&#xff0c;以实现资源利用的均衡和性能优化。其原理和算法如下&#xff1a; 原理…

ceph介绍

一、前言 Ceph 是一个完全分布式的系统&#xff0c;它将数据分布在整个集群中的多个节点上&#xff0c;以实现高可用性和容错性&#xff0c;ceph支持对象存储、块存储、文件存储所以被称为统一存储&#xff0c;ceph的架构由以下组件组成:mon、mgr、osd、mds、cephfs、rgw&#…

(最新)华为 2024 届实习招聘-硬件通⽤/单板开发——第十一套和十二套

&#xff08;最新&#xff09;华为 2024 届实习招聘-硬件通⽤/单板开发——第十一套和十二套 部分题目分享&#xff0c;完整版带答案(有答案和解析&#xff0c;答案非官方&#xff0c;未仔细校正&#xff0c;仅供参考&#xff09;&#xff08;共十套&#xff09;获取&#xff…

「GO基础」文件名规范、关键字与标识符

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」…

选购AWS服务时需要注意哪些问题?九河云详细评测

随着云计算技术的广泛应用,亚马逊网络服务(AWS)受到越来越多企业的欢迎。这是因为他们提供了丰富的云计算产品和服务,可满足企业不同阶段的IT需求。但在选购AWS服务时,企业仍需谨慎考虑以下几个方面&#xff1a; 首先要确定自身的需求&#xff0c;并评估成本效益。企业在选择A…

[C++][算法基础]有向图求最短路径(Floyd)

给定一个 n 个点 m 条边的有向图&#xff0c;图中可能存在重边和自环&#xff0c;边权可能为负数。 再给定 k 个询问&#xff0c;每个询问包含两个整数 x 和 y&#xff0c;表示查询从点 x 到点 y 的最短距离&#xff0c;如果路径不存在&#xff0c;则输出 impossible。 数据保…

平板设备IP地址设置指南

在数字化时代&#xff0c;平板电脑作为便携且功能强大的设备&#xff0c;广泛应用于日常生活和工作中。为了确保平板能够正常接入网络并与其他设备进行通信&#xff0c;正确设置IP地址是至关重要的。虎观小二将为您介绍如何设置平板的IP地址&#xff0c;帮助您轻松完成网络配置…