C++构造和折构函数详解,超详细!

个人主页:PingdiGuo_guo

收录专栏:C++干货专栏

大家龙年好呀,今天我们来学习一下C++构造函数和折构函数。

文章目录

1.构造函数

1.1构造函数的概念

1.2构造函数的思想

1.3构造函数的特点

1.4构造函数的作用

1.5构造函数的操作

1.6构造函数的分类

1.6.1默认构造函数(Default Constructor)

1.6.2带参数构造函数(Parameterized Constructor)

1.6.3拷贝构造函数(Copy Constructor)

1.6.4移动构造函数(Move Constructor)

1.6.5委托构造函数(Delegating Constructor)

1.6.6虚拟构造函数(Virtual Constructor)

1.7构造函数的练习

1.7.1题目

1.7.2步骤

1.7.3代码

2.折构函数

2.1折构函数的概念

2.2折构函数的思想

2.3折构函数的特点

2.4折构函数的作用

2.5折构函数的操作

2.6折构函数的分类

2.6.1默认析构函数

2.6.2有特定目的的析构函数

3.构造函数和折构函数的利弊

3.1利

3.2弊

4.总结


1.构造函数

1.1构造函数的概念

构造函数是C++中的特殊成员函数,用于初始化新创建的对象。当一个类的对象被声明并实例化时,构造函数自动被调用。它的主要作用是确保对象在其生命周期开始时就处于有效状态。

1.2构造函数的思想

构造函数的思想是在创建对象时,用于初始化对象的成员变量和执行其他必要的操作。构造函数在对象创建时自动调用,不需要手动调用。构造函数的主要目的是确保对象被正确地初始化,以便在使用对象时不会出现未定义的行为或错误。

1.3构造函数的特点

1.构造函数的名称与类名称相同,并且没有返回类型(包括void类型),包括默认构造函数和带参数的构造函数。

2.构造函数可以重载,即在同一个类中可以定义多个具有不同参数列表的构造函数。

3.构造函数可以带有参数,在创建对象时,可以根据传递的参数值来初始化对象的成员变量。

4.构造函数可以进行一些初始化操作,例如分配内存、调用其他对象的构造函数等。

5.构造函数可以被继承,子类可以调用父类的构造函数来初始化父类的成员变量。

1.4构造函数的作用

1.对象的初始化:构造函数用于初始化对象的成员变量,确保对象在创建时具有正确的初始状态。

2.分配和初始化成员变量:构造函数可以分配并初始化类的成员变量,以便在对象创建时设置默认值或特定的初始状态。

3.进行必要的前置操作:构造函数可以执行一些必要的前置操作,例如打开文件、连接数据库等。

4.为对象分配内存:构造函数负责为对象分配内存空间,这通常发生在通过 new 运算符创建对象时。

5.链接到其他对象或资源:构造函数可以将对象链接到其他对象或资源,以便对象能够使用这些外部资源。

6.初始化对象的状态:构造函数可以设置对象的初始状态,例如设置指针成员变量为 null、设置计数器为 0 等。

7.执行其他必要的操作:构造函数还可以执行其他与对象创建相关的必要操作,如申请资源、注册回调函数等。

8.为派生类提供基类的初始化:在派生类的构造函数中,可以通过调用基类的构造函数来初始化继承自基类的成员变量。

1.5构造函数的操作

1. 定义类结构:
 

class Book {
private:
char* title; // 私有成员变量,用于存储动态分配的标题字符串public:
// 构造函数声明
Book(const char* t);
};



2. 实现构造函数:
在类外部实现构造函数,它负责接收一个 C 风格字符串并将其复制到动态分配的内存中。
 

Book::Book(const char* t) {
// 计算字符串长度(包括终止符 '\0')
size_t len = strlen(t) + 1;// 动态分配内存
title = new char[len];// 使用标准库函数strcpy复制字符串
strcpy(title, t);
}




3. 构造函数操作:
当创建 Book 对象时,构造函数会被自动调用:
 

int main() {
Book book("The Title of the Book"); // 这里调用了构造函数
// ...
return 0;
}


在上述代码中,当我们创建 book对象时,传入的字符串 "The Title of the Book"将被复制到通过 new分配的内存空间中。

1.6构造函数的分类

构造函数可以分为以下几种分类:

1.6.1默认构造函数(Default Constructor)

如果一个类没有定义任何构造函数,那么编译器会自动生成一个默认构造函数。默认构造函数没有任何参数,并且不进行任何初始化操作。

class MyClass {
public:// 默认构造函数MyClass() {// 进行初始化操作}
};int main() {// 创建一个对象,调用默认构造函数MyClass obj;return 0;
}

1.6.2带参数构造函数(Parameterized Constructor)

带参数构造函数接收一定数量和类型的参数,用于对对象的成员变量进行初始化。通过传递不同的参数值,可以创建具有不同初始状态的对象。

class MyClass {
public:// 带参数构造函数MyClass(int value) {// 进行初始化操作,使用参数value对对象进行初始化}
};int main() {// 创建一个对象,调用带参数构造函数MyClass obj(10);return 0;
}

1.6.3拷贝构造函数(Copy Constructor)

拷贝构造函数是一种特殊的构造函数,用于创建一个新对象,并将现有对象的值复制到新对象中。拷贝构造函数通常用于对象之间的值传递或对象的复制。

class MyClass {
public:// 拷贝构造函数MyClass(const MyClass& other) {// 进行拷贝操作,将other对象的值复制到当前对象中}
};int main() {// 创建一个对象,调用拷贝构造函数MyClass obj1;MyClass obj2 = obj1;  // 或者 MyClass obj2(obj1);return 0;
}

1.6.4移动构造函数(Move Constructor)

移动构造函数是C++11引入的一种特殊构造函数,用于将右值引用参数转移或"窃取"其资源,而不是进行复制。移动构造函数可以提高程序的效率和性能。

class MyClass {
public:// 移动构造函数MyClass(MyClass&& other) {// 进行移动操作,将other对象的资源移动到当前对象中}
};int main() {// 创建一个对象,调用移动构造函数MyClass obj1;MyClass obj2 = std::move(obj1);  // 或者 MyClass obj2(std::move(obj1));return 0;
}

1.6.5委托构造函数(Delegating Constructor)

委托构造函数是C++11引入的一种特殊构造函数,它允许一个构造函数调用同一个类的另一个构造函数,以避免代码冗余。

class MyClass {
public:// 默认构造函数MyClass() : MyClass(0) {// 委托给带参数的构造函数}// 带参数构造函数MyClass(int value) {// 进行初始化操作,使用参数value对对象进行初始化}
};int main() {// 创建一个对象,调用默认构造函数MyClass obj;return 0;
}

1.6.6虚拟构造函数(Virtual Constructor)

虚拟构造函数是一种在基类中声明的构造函数,用于在派生类中动态创建基类对象。虚拟构造函数是通过在基类中声明纯虚函数来实现的。

class Base {
public:// 虚拟构造函数virtual Base* clone() const {return new Base(*this);}// 其他成员函数和数据成员
};class Derived : public Base {
public:// 虚拟构造函数的重写virtual Derived* clone() const {return new Derived(*this);}// 其他成员函数和数据成员
};int main() {// 创建一个派生类对象,调用虚拟构造函数的重写Base* basePtr = new Derived();Base* copy = basePtr->clone();// 其他操作delete basePtr;delete copy;return 0;
}

1.7构造函数的练习

1.7.1题目

设计并实现一个 Person类,其中包含姓名和年龄属性,并编写一个自定义构造函数来初始化这些属性。

1.7.2步骤

1. 定义 `Person` 类结构,声明私有成员变量。
2. 编写构造函数,接受姓名(字符串类型)和年龄(整型)作为参数。
3. 在构造函数内,对传入的参数进行有效性检查(可选)。
4. 将传入的参数值赋给对应的成员变量。

1.7.3代码

// Step 1: 定义 Person 类
class Person {
private:std::string name;int age;public:// Step 2: 编写构造函数Person(const std::string& n, int a) {// Step 3: 参数有效性检查(例如年龄应该大于0)if (a < 0) {throw std::invalid_argument("Age must be positive.");}// Step 4: 赋值给成员变量name = n;age = a;}// 其他成员函数...
};// 使用构造函数创建一个 Person 对象
int main() {Person person("John Doe", 30);return 0;
}

2.折构函数

2.1折构函数的概念

析构函数是C++中另一种特殊的成员函数,它与构造函数相反,在对象生命周期结束时(例如对象的作用域结束或者delete一个动态分配的对象时)自动调用。析构函数主要用于清理工作,如释放内存、关闭文件等。

2.2折构函数的思想

析构函数是一种特殊的成员函数,在对象销毁时自动调用,用于释放对象所占用的资源。

析构函数与构造函数相对应,构造函数用于对象的初始化,而析构函数用于对象的清理与释放。

2.3折构函数的特点

1.析构函数没有参数,且没有返回值。

2.析构函数的名称与类名相同,前面加上波浪号(~)作为前缀。

3.只能有一个析构函数,且不能被继承或重载。

4.析构函数不能被显式地调用,不能被重载。

5.对象销毁时,析构函数会自动调用,从而完成对象的销毁和资源的释放。

6.析构函数按照对象的创建顺序的逆序调用,即先创建的对象后销毁。

2.4折构函数的作用

1.释放动态分配的内存或资源。

2.关闭打开的文件、数据库连接等。

3.清理对象中的临时数据和状态。

4.执行其他清理和释放操作。

2.5折构函数的操作

1. 定义析构函数:
在类内部声明析构函数,它将在 Book 对象生命周期结束时(例如,超出作用域或显式销毁)自动调用。
 

class Book {
// ...
public:
// 析构函数声明
~Book();
};



2. 实现析构函数:
在类外部实现析构函数,它负责释放之前构造函数中动态分配的内存。
 

Book::~Book() {
// 检查指针是否已经分配过内存
if (title != nullptr) {
delete[] title; // 释放内存
title = nullptr; // 设置为 nullptr 防止悬挂指针
}
}



3. 析构函数操作:
析构函数的操作是自动的,不需要程序员显式调用。当 Book对象离开其作用域时,析构函数会自动执行。
 

int main() {
{
Book book("The Title of the Book"); // 创建对象时构造函数被调用
} // 这里 book 作用域结束,析构函数将被自动调用,释放 title 的内存
return 0;
}


在上述代码中,当 book 对象超出作用域时,析构函数将被调用,释放之前为 title分配的内存。这样就确保了程序不会出现内存泄漏的问题。

2.6折构函数的分类

析构函数的分类主要分为默认析构函数和有特定目的的析构函数。

2.6.1默认析构函数

如果在类中没有显式定义析构函数,编译器会自动生成一个默认的析构函数。默认析构函数会自动释放对象占用的内存,但不执行任何其他操作。


 

class MyClass {
public:// 构造函数MyClass() {// 构造函数的代码}// 默认析构函数~MyClass() {// 自动生成的析构函数,无需显式定义}
};

2.6.2有特定目的的析构函数

有些情况下,需要在对象销毁时执行特定的清理操作,例如释放资源、关闭文件、释放动态分配的内存等。这时可以自定义析构函数,并在其中编写相应的清理代码。


 

class MyClass {
private:int* ptr; // 动态分配的内存指针public:// 构造函数MyClass() {ptr = new int[10]; // 动态分配内存}// 有特定目的的析构函数~MyClass() {delete[] ptr; // 释放动态分配的内存}
};

在上述代码中,我们定义了一个具有特定目的的析构函数,用于释放动态分配的内存。当对象销毁时,析构函数会自动被调用,执行内存释放操作。

需要注意的是,每个类只能有一个析构函数,不能重载析构函数。析构函数没有参数,也没有返回值。析构函数的名称与类名称相同,并在前面加上波浪线(~)作为标识。

使用析构函数可以确保在对象生命周期结束时进行清理工作,避免内存泄漏和资源浪费的问题。同时,通过自定义析构函数,可以根据具体需求执行特定的清理操作。

3.构造函数和折构函数的利弊

3.1利


- 构造函数确保了对象从一开始就处于已知的良好状态。
- 析构函数提供了自动资源管理机制,减少内存泄漏和其他资源泄露的风险。



3.2弊


- 如果构造函数或析构函数内部逻辑复杂,可能影响程序性能或增加错误的可能性。
- 构造函数抛出异常会导致未初始化的对象,而析构函数如果在异常处理期间抛出异常,则可能导致程序行为不可预测。

4.总结

本篇博客到这里就结束了,感谢大家的支持与观看,如果有好的建议欢迎留言,谢谢大家啦!

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

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

相关文章

P1028 [NOIP2001 普及组] 数的计算题解

题目 给出正整数n&#xff0c;要求按如下方式构造数列&#xff1a; 只有一个数字n的数列是一个合法的数列。在一个合法的数列的末尾加入一个正整数&#xff0c;但是这个正整数不能超过该数列最后一项的一半&#xff0c;可以得到一个新的合法数列。 请你求出&#xff0c;一共…

提高效率!企业短信通道账单拆分一键处理,干货分享

**提高效率!企业短信通道账单拆分一键处理,干货分享! 昨天从硬盘里看到2019年写的 账单拆分案列,这里分享给大家 文章目录 **提高效率!企业短信通道账单拆分一键处理,干货分享!背景企业短信通道账单展示干货来了用python拆分短信账号最后短信通道账单拆分后的处理。最后…

C#,最大公共子序列(LCS,Longest Common Subsequences)的算法与源代码

1 最大公共子序列 最长的常见子序列问题是寻找两个给定字符串中存在的最长序列。 最大公共子序列算法&#xff0c;常用于犯罪鉴定、亲子鉴定等等的 DNA 比对。 1.1 子序列 让我们考虑一个序列S<s1&#xff0c;s2&#xff0c;s3&#xff0c;s4&#xff0c;…&#xff0c;…

算法------(11)并查集

例题&#xff1a; &#xff08;1&#xff09;Acwing 836.合并集合 并查集就是把每一个集合看成一棵树&#xff0c;记录每个节点的父节点。合并集合就是把一棵树变成另一棵树的子树&#xff0c;即把一棵树的父节点变为另一棵树的父节点的儿子。查询是否在同一集合就是看他们的根…

02.数据结构

一、单链表 作用&#xff1a;用于写邻接表&#xff1b; 邻接表作用&#xff1a;用于存储图或树&#xff1b; 1、用数组模拟单链表 #include<iostream> using namespace std;const int N 100010;// head 表示头结点的下标 // e[i] 表示结点i的值 // ne[i] 表示结点i的…

【OrangePi Zero2的系统移植】交叉编译工具链配置、wiringOP库、智能分类工程代码

一、交叉编译工具链配置 二、交叉编译wiringOP库 三、交叉编译智能分类工程代码 四、Makefile 用于编译 WiringPi 库 一、交叉编译工具链配置 1、关于编译 编译是指将源代码文件&#xff08;如C/C文件&#xff09;经过预处理、编译、汇编和链接等步骤&#xff0c;转换为可执…

开发JSP自定义标记

开发JSP自定义标记 您已经学习了如何用JavaBean处理JSP页面的业务逻辑。除此以外,您还可以用自定义标记处理JSP应用程序中反复出现的业务逻辑要求。 tag是程序中使用的执行重复性任务的可重用单元。例如, 是使主体文本在网页中间出现的HTML标记。JSP可用于创建于XML标记类似…

【Rust】——猜数游戏

&#x1f383;个人专栏&#xff1a; &#x1f42c; 算法设计与分析&#xff1a;算法设计与分析_IT闫的博客-CSDN博客 &#x1f433;Java基础&#xff1a;Java基础_IT闫的博客-CSDN博客 &#x1f40b;c语言&#xff1a;c语言_IT闫的博客-CSDN博客 &#x1f41f;MySQL&#xff1a…

【数据结构与算法】【小白也能学的数据结构与算法】递归 分治 迭代 动态规划 无从下手?一文通!!!

&#x1f389;&#x1f389;欢迎光临&#x1f389;&#x1f389; &#x1f3c5;我是苏泽&#xff0c;一位对技术充满热情的探索者和分享者。&#x1f680;&#x1f680; &#x1f31f;特别推荐给大家我的最新专栏《数据结构与算法&#xff1a;初学者入门指南》&#x1f4d8;&am…

例37:爱好选择

建立一个新的EXE工程&#xff0c;放两个单选&#xff0c;两个复选框如图33。 图33 输入代码&#xff1a; Sub Form1_Check1_BN_Clicked(hWndForm As hWnd, hWndControl As hWnd)Text1.Text ""If Check1.Value ThenText1.Text"你喜欢" & Check1.Cap…

Linux运行级别 | 管理Linux服务

Linux运行级别 级别&#xff1a; 0关机1单用户2多用户但是不运行nfs网路文件系统3默认的运行级别&#xff0c;给一个黑的屏幕&#xff0c;只能敲命令4未使用5默认的运行级别&#xff0c;图形界面6重启切换运行级别&#xff1a; init x管理Linux服务 systemctl命令&#xf…

鸿蒙实战开发-全局UI方法的功能

主要开发内容 时间调节 使用全局UI的方法定义日期滑动选择器弹窗并弹出。 操作说明&#xff1a;首先创建一个包含按钮的用户界面&#xff0c;当用户点击“时间设置”按钮时&#xff0c;会弹出调用TimePickerDialog组件的show方法&#xff0c;显示一个时间选择对话框&#xff…

[word] word表格内容自动编号 #经验分享#微信#其他

word表格内容自动编号 在表格中的内容怎么样自动编号&#xff1f;我们都知道Word表格和Excel表格有所不同&#xff0c;Excel表格可以轻松自动编号&#xff0c;那么在Word表格中如何自动编号呢&#xff1f; 1、选中内容后&#xff0c;点击段落-自动编号&#xff0c;选择其中一…

vscode远程连接失败

目录 解决方案尝试1解决方案尝试2 解决方案尝试1 最近通过vscode一直使用腾讯云的服务器作为远程开发环境&#xff0c;以前一直很好用。 直到最近重装了系统之后&#xff0c;发现vscode没法对云服务器进行连接了&#xff0c;即使在远程主机添加了本地的公钥也不行。直接报错:…

ChatGpt报错:We ran into an issue while authenticating you解决办法

在登录ChatGpt时报错&#xff1a;Oops&#xff01;,We ran into an issue while authenticating you.(我们在验证您时遇到问题)&#xff0c;记录一下解决过程。 完整报错&#xff1a; We ran into an issue while authenticating you. If this issue persists, please contact…

qt-C++笔记之判断一个QLabel上有没有load图片

qt-C笔记之判断一个QLabel上有没有load图片 code review! 在Qt框架中&#xff0c;QLabel是用来显示文本或者图片的一个控件。如果你想判断一个QLabel控件上是否加载了图片&#xff0c;你可以检查它的pixmap属性。pixmap属性会返回一个QPixmap对象&#xff0c;如果没有图片被加…

error: object ‘FastMNNIntegration‘ not found

加载一个包即可 library(SeuratWrappers) #运行fastmnn之前&#xff0c;需要加载&#xff0c;否则报错 obj <- IntegrateLayers(object obj, method FastMNNIntegration,new.reduction "integrated.mnn",verbose FALSE )

C#系列-使用 Minio 做图片服务器实现图片上传 和下载(13)

1、Minio 服务器下载和安装 要在本地安装和运行 MinIO 服务器&#xff0c;你可以按照以下 步骤进行操作&#xff1a; 1. 访问 MinIO 的官方网站&#xff1a;https://min.io/&#xff0c;然后 点击页面上的”Download”按钮。 2. 在下载页面上&#xff0c;选择适合你操作系统的 …

Docker 有哪些常见的用途?

Docker 是一种容器化技术&#xff0c;它允许应用程序在不同的环境之间具有一致的运行环境。这使得 Docker 在开发和运维领域中非常受欢迎&#xff0c;因为它简化了应用程序的部署和管理。以下是 Docker 的一些常见用途&#xff1a; 快速部署应用程序 Docker 允许开发人员和运…

Hive窗口函数详解

一、 窗口函数知识点 1.1 窗户函数的定义 窗口函数可以拆分为【窗口函数】。窗口函数官网指路&#xff1a; LanguageManual WindowingAndAnalytics - Apache Hive - Apache Software Foundationhttps://cwiki.apache.org/confluence/display/Hive/LanguageManual%20Windowing…