C++|构造函数和析构函数

news2025/3/17 16:07:45

一、构造函数

构造函数是一种特殊的成员函数,主要用于创建对象时对对象进行初始化操作,即专门用于构造新对象,并赋值对象的成员数据。

在 C++ 里,构造函数的名称和类名相同,并且没有返回类型。当创建类的对象时,构造函数会自动被调用。

构造函数可以在类内也可在类外定义。

构造函数在类内的定义格式如下:

        类名(参数列表)

        {        函数体;        }

在类外定义构造函数的形式如下:

        类名::类名(形参列表)

        {        函数体;        }

构造函数可以重载,即可以有多个构造函数,因为构造函数有参数列表,构造函数一般为公有权限public。

定义对象时,系统会自动调用构造函数。同时若无主动定义,系统会自动生成一个默认的构造函数,该默认构造函数无参数,也不对数据成员初始化,仅为对象分配存储空间。如果显式地为类定义了构造函数,系统将不再为类提供默认构造函数。

#include <iostream>
using namespace std;
class Rectangle {
private:
    double length;
    double width;

public:
    // 构造函数
    Rectangle(double l, double w) {
        length = l;
        width = w;
    }

    double getArea() {
        return length * width;
    }
};

int main() {
    // 创建 Rectangle 对象并调用构造函数进行初始化
    Rectangle rect(5.0, 3.0);
    cout << "Rectangle area: " << rect.getArea() << endl;
    return 0;
}

1.默认构造函数

1.1系统自动生成默认构造函数

它只负责为对象分配存储空间,而不对数据进行初始化,一般为随机值。

1.2自定义默认构造函数

(1)默认参数只能最上面给,不能多处给定(避免不一致)
(2)带默认值的参数必须在最右面。
(3)有默认参数时,注意避免重定义。
上面三点和普通带默认值的函数一样。

2.构造函数的重载

在 C++ 中,构造函数的重载是指在一个类中可以定义多个具有相同名称(类名)但参数列表不同的构造函数。通过构造函数重载,我们可以使用不同的方式来初始化对象,以满足不同的需求。

构造函数重载的规则

  • 函数名相同:所有重载的构造函数的名称都必须与类名相同。
  • 参数列表不同:参数列表的不同可以体现在参数的个数、类型或顺序上。
  • 返回类型:构造函数没有返回类型,也不能使用void作为返回类型。
  • #include <iostream>
    #include <string>
    using namespace std;
    class Student {
    private:
        string name;
        int age;
        double score;
    
    public:
        // 默认构造函数
        Student() {
            name = "Unknown";
            age = 0;
            score = 0.0;
            cout << "Default constructor called." << endl;
        }
    
        // 带一个参数的构造函数,只初始化姓名
        Student(const string& n) {
            name = n;
            age = 0;
            score = 0.0;
            cout << "Constructor with one parameter called." << endl;
        }
    
        // 带两个参数的构造函数,初始化姓名和年龄
        Student(const string& n, int a) {
            name = n;
            age = a;
            score = 0.0;
            cout << "Constructor with two parameters called." <<endl;
        }
    
        // 带三个参数的构造函数,初始化姓名、年龄和分数
        Student(const string& n, int a, double s) {
            name = n;
            age = a;
            score = s;
            cout << "Constructor with three parameters called." << endl;
        }
    
        // 显示学生信息的函数
        void displayInfo() {
            cout << "Name: " << name << ", Age: " << age << ", Score: " << score << endl;
        }
    };
    
    int main() {
        // 使用默认构造函数创建对象
        Student s1;
        s1.displayInfo();
    
        // 使用带一个参数的构造函数创建对象
        Student s2("Alice");
        s2.displayInfo();
    
        // 使用带两个参数的构造函数创建对象
        Student s3("Bob", 20);
        s3.displayInfo();
    
        // 使用带三个参数的构造函数创建对象
        Student s4("Charlie", 22, 85.5);
        s4.displayInfo();
    
        return 0;
    }

3. 类定义时成员变量初始化

在C++11中允许在类定义时对成员变量初始化。

class A
{
    public:
        A(){ }
        void show()
        {
            cout << "m_a = " << m_a << endl;
            cout << "m_b = " << m_b << endl;
        }
    private:
        int m_a = 10;//类定义时初始化
        int m_b; //没有初始化
};

int main()
{
    A a;
    a.show();
    return 0;
}

如果在构造函数中也有赋值,以赋值的为准,这个就和普通变量一样,初始化的值会被后面的赋值覆盖。

4.构造函数与初始化列表

构造函数也可以采用构造初始化列表的方式对数据成员进行初始化。

Date::Date(int y,int m,int d):year(y),month(m),day(d)

{}

二、析构函数

当对象的生存期结束时,系统就会自动执行析构函数回收其数据成员所分配的内存空间。

析构函数的定义格式为:

~类名();//没有返回值,没有参数

(1)析构函数名是由“~”加类名组成的。
(2)析构函数没有参数、没有返回值,不能重载。
(3)一个类有且仅有一个析构函数,必须为public。
(4)在对象的生存期结束时,由系统自动调用析构函数。
(5)如果没有定义析构函数,系统会自动生成一个默认的析构函数。

面试题:在main之前可以执行别的函数吗?在main结束后可以执行别的函数吗?

main函数之前执行函数

  • 可以通过使用全局对象的构造函数来实现。在程序启动时,全局对象会在main函数之前被初始化,其构造函数中的代码会在main函数之前执行。

main函数之后执行函数

  • 对于 C++ ,全局对象的析构函数会在main函数结束后执行,因为全局对象的生命周期在程序结束时才结束,所以析构函数中的代码可以在main函数之后执行。

三、构造和析构的调用顺序

先构造的后析构,后构造的先析构

当然函数和析构函数调用时机和它的生命周期是密不可分的。

下面归纳一下什么时候调用构造函数和析构函数。
(1)全局对象(生命周期:程序运行时创建,程序结束时销毁)的构造函数在所有函数(包括main函数)执行之前调用。但如果一个程序中有多个文件,而不同的文件中都定义了全局对象,则这些对象的构造函数的执行顺序是不确定的。当main函数执行完毕或调用exit函数时(此时程序终止),调用其析构函数。
(2)局部对象(在函数内定义的对象,其生命周期是进入该函数创建,函数退出结束)在进入该函数建立对象时调用其构造函数。如果函数被多次调用,则在每次建立对象时都要调用构造函数。在函数调用结束时调用析构函数。
(3)如果在函数中定义了静态(static)局部对象(生命周期是第一次进入该函数创建,程序退出时销毁),则只在程序第一次调用此函数建立对象时调用一次构造函数,在调用结束时对象并不被释放,因此也不调用析构函数,只在main函数结束或调用exit函数结束程序时,才调用析构函数。
(4)动态创建的对象,是调用new关键字创建函数时调用构造函数,调用delete函数销毁对象时调用析构函数

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

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

相关文章

不像人做的题————十四届蓝桥杯省赛真题解析(上)A,B,C,D题解析

题目A&#xff1a;日期统计 思路分析&#xff1a; 本题的题目比较繁琐&#xff0c;我们采用暴力加DFS剪枝的方式去做&#xff0c;我们在DFS中按照8位日期的每一个位的要求进行初步剪枝找出所有的八位子串&#xff0c;但是还是会存在19月的情况&#xff0c;为此还需要在CHECK函数…

JavaScript 中 call 和 apply 的用法与区别

文章目录 前言一、 call 方法1.1 基本用法1.2 传递多个参数 二、apply 方法2.1 基本用法2.2 传递数组参数 三、call 和 apply 的区别四、实际应用场景4.1 借用方法4.2 继承与构造函数 五、总结 前言 在 JavaScript 中&#xff0c;call 和 apply 是两个非常重要的函数方法&…

面试系列|蚂蚁金服技术面【1】

哈喽&#xff0c;大家好&#xff01;今天分享一下蚂蚁金服的 Java 后端开发岗位真实社招面经&#xff0c;复盘面试过程中踩过的坑&#xff0c;整理面试过程中提到的知识点&#xff0c;希望能给正在准备面试的你一些参考和启发&#xff0c;希望对你有帮助&#xff0c;愿你能够获…

使用傅里叶变换测量声卡的频率失真

文章目录 一、说明二、关于声卡的技术详述三、实验代码获取四、结论 一、说明 假如我希望使用我的声卡来模拟软件无线电&#xff0c;利用声音而不是射频信号。我的声卡能胜任这项任务吗&#xff1f;本文将研究一种技术来找出答案。另外&#xff0c;需要了解音频技术的读者也可…

【HTML5】01-HTML摆放内容

本文介绍HTML5摆放标签的知识点。 目录 1. HTML概念 2. HTML骨架 3. 标签的关系 4. 标题标签 5. 段落标签 6. 换行和水平线 7. 文本格式化标签 8. 图像标签 图像 - 属性 9. 路径 相对路径 绝对路径 10. 超链接标签 11. 音频标签 12. 视频标签 1. HTML概念 HTM…

内存管理:

我们今天来学习一下内存管理&#xff1a; 1. 内存分布&#xff1a; 我们先来看一下我们下面的图片&#xff1a; 这个就是我们的内存&#xff0c;我们的内存分为栈区&#xff0c;堆区&#xff0c;静态区&#xff0c;常量区&#xff1b; 我们的函数栈帧开辟消耗的内存就是我们…

设计模式使用Java案例

代码设计要有可维护性&#xff0c;可复用性&#xff0c;可扩展性&#xff0c;灵活性&#xff0c;所有要使用设计模式进行灵活设计代码 创建型 简单工厂模式&#xff08;Simple Factory&#xff09; 简单工厂模式&#xff08;Simple Factory Pattern&#xff09;是一种创建型…

模运算的艺术:从基础到高阶的算法竞赛应用

在算法竞赛中&#xff0c;模运算&#xff08;取模运算&#xff09;是一个非常重要的概念&#xff0c;尤其在处理大数、防止溢出、以及解决与周期性相关的问题时。C 中的模运算使用 % 运算符&#xff0c;但它的行为和使用场景需要特别注意。 1. 模运算的基本概念 模运算是指求一…

ST电机库电流采样 三电阻单ADC

一、概述 下图是三电阻采样的电路结构 其中流过三相系统的电流I1、I2、I3遵循以下关系: 因此,为了重建流过普通三相负载的电流,在我们可以用以上公式计算的情况下,只需要对三相中的两相进行采样即可。 STM32的ADC可以很灵活的配置成同步采集两路ADC数据,…

现代密码学 | 具有保密和认证功能的安全方案

1.案例背景 1.1 2023年6月&#xff0c;微软云电子邮件泄露 事件描述&#xff1a; 2023年6月&#xff0c;属于多家美国政府机构的微软云电子邮件账户遭到非法入侵&#xff0c;其中包括了多位高级政府官员的电子邮件。据报道&#xff0c;美国国务院的10个邮件账户中共有6万封电…

一款基于Python的从常规文档里提取图片的简单工具开发方案

一款基于Python的从常规文档里提取图片的简单工具开发方案 1. 环境准备 安装必需库 pip install python-docx PyMuPDF openpyxl beautifulsoup4 pillow pip install pdfplumber # PDF解析备用方案 pip install tk # Python自带&#xff0c;无需安装工具选择 开发环…

JetBrains(全家桶: IDEA、WebStorm、GoLand、PyCharm) 2024.3+ 2025 版免费体验方案

JetBrains&#xff08;全家桶: IDEA、WebStorm、GoLand、PyCharm&#xff09; 2024.3 2025 版免费体验方案 前言 JetBrains IDE 是许多开发者的主力工具&#xff0c;但从 2024.02 版本起&#xff0c;JetBrains 调整了试用政策&#xff0c;新用户不再享有默认的 30 天免费试用…

Docker生存手册:安装到服务一本通

文章目录 一. Docker 容器介绍1.1 什么是Docker容器&#xff1f;1.2 为什么需要Docker容器&#xff1f;1.3 Docker架构1.4 Docker 相关概念1.5 Docker特点 二. Docker 安装2.1 查看Linux内核版本2.2 卸载老版本docker&#xff0c;避免产生影响2.3 升级yum 和配置源2.4 安装Dock…

Linux内核传输层UDP源码分析

一、用户数据包协议&#xff08;UDP&#xff09; 1.UDP数据报头 UDP 提供面向消息的不可靠传输&#xff0c;但没有拥塞控制功能。很多协议都使用 UDP&#xff0c;如用于 IP 网络传输音频和视频的实时传输协议 (Real-time Transport Protocol&#xff0c;RTP)&#xff0c;此类型…

FPGA学习(二)——实现LED流水灯

FPGA学习(二)——实现LED流水灯 目录 FPGA学习(二)——实现LED流水灯一、DE2-115时钟源二、控制6个LED灯实现流水灯1、核心逻辑2、代码实现3、引脚配置4、实现效果 三、模块化代码1、分频模块2、复位暂停模块3、顶层模块 四、总结 一、DE2-115时钟源 DE2-115板子包含一个50MHz…

Linux如何在设备树中表示和引用设备信息

DTS基本知识 dts 硬件的相应信息都会写在.dts为后缀的文件中&#xff0c;每一款硬件可以单独写一份xxxx.dts&#xff0c;一般在Linux源码中存在大量的dts文件&#xff0c;对于arm架构可以在arch/arm/boot/dts找到相应的dts&#xff0c;一个dts文件对应一个ARM的machie。 dtsi 值…

Matlab 汽车振动多自由度非线性悬挂系统和参数研究

1、内容简介 略 Matlab 169-汽车振动多自由度非线性悬挂系统和参数研究 可以交流、咨询、答疑 2、内容说明 略 第二章 汽车模型建立 2.1 汽车悬架系统概述 2.1.1 悬架系统的结构和功能 2.1.2 悬架分类 2.2 四分之一车辆模型 对于车辆动力学&#xff0c;一般都是研究其悬…

生活中的可靠性小案例11:窗户把手断裂

窗户把手又断了&#xff0c;之前也断过一次&#xff0c;使用次数并没有特别多。上方的图是正常的把手状态&#xff0c;断的形状如下方图所示。 这种悬臂梁结构&#xff0c;没有一个良好的圆角过渡&#xff0c;导致应力集中。窗户的开关&#xff0c;对应的是把手的推拉&#xff…

[oeasy]python074_ai辅助编程_水果程序_fruits_apple_banana_加法_python之禅

074_ai辅助编程_水果程序_fruits_加法 回忆上次内容 上次直接从模块中导入变量、函数 from my_file import pi 导入my_file.pi 并作为 pi 使用 from my_file import pi as my_pi 导入变量 并 重命名 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; …

【图论】并查集的学习和使用

目录 并查集是什么&#xff1f; 举个例子 组成 父亲数组&#xff1a; find函数&#xff1a; union函数&#xff1a; 代码实现&#xff1a; fa[] 初始化code: find code&#xff1a; 递归实现: 非递归实现: union code : 画图模拟&#xff1a; 路径压缩&#xff1a…