【C++入门到精通】C++入门 —— 类和对象(构造函数、析构函数)

news2024/9/30 1:31:29

目录

一、类的6个默认成员函数

 二、构造函数

⭕构造函数概念

⭕构造函数的特点

⭕常见构造函数的几种类型

三、析构函数

     ⭕析构函数概念

    ⭕析构函数的特点

⭕常见析构函数的几种类型

四、温馨提示


前言

         这一篇文章是上一篇的续集(这里有上篇链接)前面我们讲了C语言的基础知识,也了解了一些数据结构,并且讲了有关C++的命名空间的一些知识点以及关于C++的缺省参数、函数重载,引用 和 内联函数。也相信大家都掌握的不错,接下来博主将会带领大家继续学习有关C++比较重要的知识点——类和对象。下面话不多说坐稳扶好咱们要开车了。

一、类的6个默认成员函数

        如果一个类中什么成员都没有,简称为空类。空类中真的什么都没有吗?并不是,任何类在什么都不写时,编译器会自动生成以下6个默认成员函数。默认成员函数:用户没有显式实现,编译器会生成的成员函数称为默认成员函数

        1. 默认构造函数(Default Constructor):如果类没有定义任何构造函数,编译器会自动生成一个默认构造函数。默认构造函数没有参数,用于创建一个对象时进行初始化操作。

        2. 析构函数(Destructor):析构函数在对象被销毁时调用,用于释放对象所占用的资源,如释放动态分配的内存、关闭文件等。析构函数没有参数,且其名称以波浪线(~)开头,后跟类名。

        3. 拷贝构造函数(Copy Constructor):拷贝构造函数用于将一个已经存在的对象的数据成员复制到另一个对象中。当使用一个对象初始化另一个对象、函数参数以值传递方式传递对象、或者以值返回对象时,拷贝构造函数会被自动调用。拷贝构造函数有一个参数,类型为同类对象的引用。

        4. 拷贝赋值运算符(Copy Assignment Operator):拷贝赋值运算符用于将一个已经存在的对象的数据成员复制到另一个对象中。当使用赋值运算符=给一个已经初始化的对象赋值时,拷贝赋值运算符会被自动调用。拷贝赋值运算符有一个参数,类型为同类对象的引用,返回类型为引用。

        5. 移动构造函数(Move Constructor):移动构造函数用于将一个临时对象或者将要被销毁的对象的资源(如动态分配的内存)“移动”给另一个对象,避免了不必要的数据拷贝。移动构造函数有一个参数,类型为同类对象的引用。

        6. 移动赋值运算符(Move Assignment Operator):移动赋值运算符用于将一个临时对象或者将要被销毁的对象的资源(如动态分配的内存)“移动”给另一个对象,避免了不必要的数据拷贝。移动赋值运算符有一个参数,类型为同类对象的引用,返回类型为引用。

        需要注意的是:如果自定义了析构函数、拷贝构造函数、拷贝赋值运算符、移动构造函数或移动赋值运算符中的任何一个,编译器将不再为该类生成相应的默认成员函数。

 二、构造函数

⭕构造函数概念

        C++中的构造函数是一种特殊的成员函数,用于创建和初始化类的对象。构造函数在对象被创建时自动被调用,主要目的是为对象的数据成员提供初始值,确保对象在创建后处于合适的状态。

⭕构造函数的特点

1. 构造函数的名称必须与类名完全相同,并且没有返回类型(连void也没有)。
2. 构造函数可以有参数,用于在创建对象时提供初始化值。这些参数可以有默认值,也可以是任意类型。
3. 构造函数可以被重载,也就是可以定义多个具有相同名称但参数列表不同的构造函数。这样可以根据不同的初始化需求选择合适的构造函数。
4. 在创建对象时,会自动调用与对象匹配的构造函数。也就是说,构造函数在对象被创建的时候自动被调用,无需手动调用。
5. 构造函数可以执行一些必要的初始化操作,如动态分配内存、打开文件、初始化数据成员等。

⭕常见构造函数的几种类型

1. 默认构造函数(Default Constructor)

        没有参数的构造函数,用于创建对象时提供默认的初始值。
2. 带参构造函数(Parameterized Constructor)

        带有参数的构造函数,用于根据提供的参数初始化对象的数据成员。
3. 复制构造函数(Copy Constructor)

        以一个同类对象作为参数,用于根据已有对象创建新的对象。
4. 移动构造函数(Move Constructor)

        以一个临时对象或将要被销毁的对象作为参数,用于“移动”资源(如动态分配的内存)而不是执行数据拷贝。
5. 类型转换构造函数(Conversion Constructor)

        以其他类型的对象作为参数,用于将其他类型的对象转换为该类的对象。

        构造函数在类的定义中是以公有(public)访问权限声明的,因为它们需要被外部代码调用来创建对象。一个类可以有多个构造函数,并且可以选择性地定义它们,如果没有定义任何构造函数,编译器会自动生成一个默认构造函数。

下面是一个简单的示例,展示了一个类 ‘ Person ’ 的构造函数的定义和使用:

#include <iostream>
#include <string>

class Person {
public:
    // 默认构造函数
    Person() {
        name = "Unknown";
        age = 0;
    }

    // 带参构造函数
    Person(const std::string& n, int a) {
        name = n;
        age = a;
    }

    // 打印信息的成员函数
    void printInfo() {
        std::cout << "Name: " << name << ", Age: " << age << std::endl;
    }

private:
    std::string name;
    int age;
};

int main() {
    // 使用默认构造函数创建对象
    Person p1;
    p1.printInfo(); // 输出:Name: Unknown, Age: 0

    // 使用带参构造函数创建对象
    Person p2("John", 25);
    p2.printInfo(); // 输出:Name: John, Age: 25

    return 0;
}

        在上面的示例中,Person 类包含了一个默认构造函数和一个带参构造函数。通过这两个构造函数,可以选择使用不同的方式创建 Person 对象,从而灵活地满足不同的需求。

三、析构函数

     ⭕析构函数概念

        析构函数:与构造函数功能相反,析构函数不是完成对对象本身的销毁,局部对象销毁工作是由编译器完成的。而对象在销毁时会自动调用析构函数,完成对象中资源的清理工作。它的主要作用是确保对象使用的资源被正确释放,防止资源泄漏和内存泄漏的发生。

    ⭕析构函数的特点

1. 析构函数的名称与类名相同,但前面有一个波浪线(~)作为前缀。例如,如果类名为MyClass,则对应的析构函数名为~MyClass。
2. 析构函数没有返回类型,包括void,因为它不返回任何值。
3. 析构函数不接受任何参数,因此不能被重载,每个类只能有一个析构函数。
4. 析构函数不能手动调用,它会在对象生命周期结束时自动被触发执行。对象销毁的情况包括对象超出作用域、通过delete释放了对应的动态分配内存、容器中的对象被移除等。
5. 当对象的析构函数被调用时,它会自动调用成员对象的析构函数,并按照它们被定义的顺序进行销毁。
6. 如果没有显式定义析构函数,编译器会默认生成一个空的析构函数,即不做任何操作。

        析构函数通常用于在对象销毁时执行一些必要的清理工作,比如释放动态分配的内存、关闭文件句柄、释放其他类型的资源等。通过析构函数,可以确保对象所使用的资源被正确释放,避免资源泄漏和内存泄漏的问题。

下面是一个简单的示例,展示了一个类FileHandler的析构函数的定义和使用

#include <iostream>
#include <fstream>

class FileHandler {
public:
    FileHandler(const std::string& filename) {
        file.open(filename);
        if (!file) {
            std::cout << "Failed to open file " << filename << std::endl;
        }
    }

    ~FileHandler() {
        if (file.is_open()) {
            file.close();
            std::cout << "File closed." << std::endl;
        }
    }

    void writeToFile(const std::string& data) {
        file << data << std::endl;
    }

private:
    std::ofstream file;
};

int main() {
    FileHandler handler("example.txt");
    handler.writeToFile("Hello, world!");

    return 0;
}

        在上面的示例中,FileHandler类封装了一个文件句柄,其中构造函数用于打开文件并检查是否成功打开,而析构函数则负责在对象销毁时关闭文件。在main函数中,创建了一个FileHandler对象handler并写入数据,当对象handler超出作用域时,析构函数会被自动调用,关闭文件。

        通过定义适当的析构函数,可以确保对象的资源在对象销毁时被正确释放,从而保证程序运行的安全性和可靠性。也值得注意的是,在使用动态分配的内存或其他相关资源时,需要显式定义析构函数,以免造成资源泄漏。

⭕常见析构函数的几种类型

根据特定的需求和情况,常见的析构函数可以分为以下四种类型:

        1. 默认析构函数(Default Destructor):如果没有显式定义析构函数,编译器会隐式地生成一个默认的析构函数。默认析构函数没有任何实现内容,它的作用仅仅是调用成员对象的析构函数,并按照它们的定义顺序进行销毁。

class MyClass {
    // 在这里没有显式定义析构函数
    // 编译器会自动生成一个默认析构函数
};

        2. 虚析构函数(Virtual Destructor):当一个类被继承时,通常应该考虑使用虚析构函数。虚析构函数在基类中声明为虚函数,可以确保当通过指向基类的指针删除一个基类对象时,实际上会调用到派生类的析构函数。这是为了确保析构函数正确释放所有的资源,包括派生类自己的资源。

class MyBaseClass {
public:
    virtual ~MyBaseClass() { // 声明为虚函数
        // 析构函数的实现
    }
};

class MyDerivedClass : public MyBaseClass {
public:
    ~MyDerivedClass() {
        // 派生类析构函数的实现
    }
};

        3. 纯虚析构函数(Pure Virtual Destructor):纯虚析构函数是一个没有具体实现的虚析构函数。它的存在是为了将基类定义为抽象类,即不能实例化的类。纯虚析构函数要求派生类必须提供具体的实现。

class AbstractClass {
public:
    virtual ~AbstractClass() = 0; // 纯虚析构函数,没有实现
};

AbstractClass::~AbstractClass() {
    // 纯虚析构函数的实现
}

class ConcreteClass : public AbstractClass {
public:
    ~ConcreteClass() {
        // 派生类的析构函数实现
    }
};

        4. 自定义析构函数(Custom Destructor):自定义析构函数根据类的具体需求定义。它可以用于释放动态分配的内存、关闭文件句柄、释放其他资源等。自定义的析构函数应该根据类的设计在适当的时候进行资源的清理和回收。

class MyClass {
public:
    ~MyClass() {
        // 自定义的析构函数实现
        // 释放资源,关闭文件等
    }
};

        要根据你的需求选择适当的析构函数类型。大多数情况下,默认析构函数已足够满足基本需求,但当涉及到多态性和继承时,可能需要使用虚析构函数。对于抽象类,可以使用纯虚析构函数。自定义析构函数提供了更灵活的资源清理能力。

四、温馨提示

        感谢您对博主文章的关注与支持!在阅读本篇文章的同时,我们想提醒您留下您宝贵的意见和反馈。如果您喜欢这篇文章,可以点赞、评论和分享给您的同学,这将对我提供巨大的鼓励和支持。另外,我们计划在未来的更新中持续探讨与本文相关的内容。我们会为您带来更多关于C++以及编程技术问题的深入解析、应用案例和趣味玩法等。请继续关注我们的更新,不要错过任何精彩内容!

        我们将会不断为大家带来更多精彩、有趣的文章和内容。没有你们的关注,我们的努力就失去了意义。与这篇文章相关的内容也将陆续推出,希望你们能够一直关注我们的动态。余下的拷贝构造函数、赋值运算符重载、const成员、取地址及const取地址操作符重载详见下回分解下一篇链接:

        再次感谢您的支持和关注。我们期待与您建立更紧密的互动,共同探索C++、算法和编程的奥秘。祝您生活愉快,排便顺畅!

 

 

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

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

相关文章

qt服务器 网络聊天室

widget.cpp #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);//给服务器指针实例化空间server new QTcpServer(this); }Widget::~Widget() {delete ui; }//启动…

C++ malloc/free和new/delete

1.malloc和free malloc是开辟内存单元的库函数&#xff1b; malloc不会调用构造函数&#xff1b; free只是释放malloc所开辟的空间&#xff1b; free不会调用析构函数。 #include <iostream> using namespace std; class A { public:A(int i0) { cout << "A&…

BUG分析以及BUG定位

一般来说bug大多数存在于3个模块&#xff1a; 1、前台界面&#xff0c;包括界面的显示&#xff0c;兼容性&#xff0c;数据提交的判断&#xff0c;页面的跳转等等&#xff0c;这些bug基本都是一眼可见的&#xff0c;不太需要定位&#xff0c;当然也不排除一些特殊情况&#xf…

25.6 matlab里面的10中优化方法介绍—— 遗传算法(matlab程序)

1.简述 遗传算法&#xff08;Genetic Algorithm, GA&#xff09;是模拟达尔文生物进化论的自然选择和遗传学机理的生物进化过程的计算模型&#xff0c;是一种通过模拟自然进化过程搜索最优解&#xff08;所找到的解是全局最优解&#xff09;的方法。 参数编码、初始群体的设定…

「乐天世界」VoxEdit 创作大赛

&#x1f389;参加激动人心的乐天世界 VoxEdit 大赛&#xff01;&#x1f3a8; 召集所有体素艺术家和韩国文化爱好者&#xff01;您准备好展示自己的体素设计技能&#xff0c;用自己的独特风格为乐天世界心爱的吉祥物 Lotty 赋予生命了吗&#xff1f;让我们看看您的想象力和设计…

Acwing.91 最短Hamilton路径(动态规划)

题目 给定一张n个点的带权无向图&#xff0c;点从0~n-1标号&#xff0c;求起点0到终点n-1的最短Hamilton路径。Hamilton路径的定义是从0到n-1不重不漏地经过每个点恰好一次。 输入格式 第—行输入整数n。 接下来n行每行n个整数&#xff0c;其中第i行第j个整数表示点i到j的距…

使用go与智能合约交互之abi调用

上一篇文章&#xff0c;我们讲解了go如何使用函数选择器的方式进行智能合约的调用&#xff0c;接下来让我们一起学习一下如何使用abi的方式进行智能合约的调用 本系列课程&#xff1a; 第一节&#xff1a;使用go与智能合约交互之函数选择器调用 第二节&#xff1a;使用go与智能…

堆喷射的小例子

引自&#xff1a;https://blog.csdn.net/lixiangminghate/article/details/53413863 照着作者的意思&#xff0c;自己的测试代码&#xff1a; #include <iostream> #include <windows.h> #include <stdio.h>class base {char m_buf[8]; public:virtual int…

上传图片到腾讯云对象存储桶cos

1、首先登录腾讯云官网控制台 进入对象存储页面 2、找到跨越访问CIRS设置 配置规则 点击添加规则 填写信息 3、书写代码 这里用VUE3书写 <template><div><input type"file" change"handleFileChange" /></div> </template&g…

JS学习之ES6

一、ES简介 ES6是一个泛指&#xff0c;指EDMAJavaScript之后的版本。它是JS的语言标准。 Nodejs 简介&#xff1a;它是一个工具&#xff0c;主攻服务器&#xff0c;使得利用JS也可以完成服务器代码的编写。 安装&#xff1a; 安装Nodejs的同时&#xff0c;会附带一个npm命令…

QT--day4(定时器事件、鼠标事件、键盘事件、绘制事件、实现画板、QT实现TCP服务器)

QT实现tcpf服务器代码&#xff1a;&#xff08;源文件&#xff09; #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);//给服务器指针实例化空间server new QTc…

无涯教程-jQuery - show( )方法函数

show()方法仅显示匹配元素中的每个元素(如果隐藏)。此方法还有另一种形式&#xff0c;可以控制动画的速度。 show( ) - 语法 selector.show( ); show( ) - 示例 以下是一个简单的示例&#xff0c;简单说明了此方法的用法- <html><head><title>The jQuer…

PostgreSQL-Centos7源码安装

卸载服务器上的pg13 本来是想删除原来的postgis重新源码安装就行,但是yum安装的PostgreSQL不能直接使用,会提示以下问题: 之前服务是用yum安装的,现在需要删除 -- 删除数据的postgis插件 drop extension postgis; drop extension postgis cascade;删除相关安装包 # 查询…

Ubuntu Server版 之 apache系列 常用配置 以及 隐藏 版本号 IP、Port 搭建服务案例

查看版本 旧的 用 httpd -v 新的 用 apache2 -v 配置检测 旧的 httpd -t 新的 apachectl configtest window用的apache 是 httpd -t Linux 中 apachectl configtest 主配置文件 之前旧版apache 是httpd 现在都改成 apache2 /etc/apache2/apache2.conf window中 httpd.con…

leetcode 2141. Maximum Running Time of N Computers(N台计算机的最大运行时间)

有n台电脑&#xff0c;数组batteries代表每块电池的电量。 每台电脑每次只能放入一块电池&#xff0c;然后电池可以任意交换&#xff0c;但电池不能充电。 所有电脑必须同时运行。 问n台电脑最多可以同时运行几分钟。 思路&#xff1a; 乍一看很复杂&#xff0c;复杂的电池交…

使用Feign出现空指针异常

说明&#xff1a;本文记录一次偶然出现的空指针异常&#xff0c;在微服务架构中&#xff0c;一个服务在调用另一个服务时&#xff0c;出现了空指针异常。 业务描述&#xff1a;在做订单超时功能时&#xff0c;大家都知道&#xff0c;可以使用RabbitMQ延迟队列&#xff0c;下单…

【视觉SLAM入门】4.3. (非线性最小二乘问题)优化算法实现-ceres和g2o, 图优化理论

"天道不争而善胜" 1. Ceres库1.1 名词解释1.2 具体例子1.3 C实现1. 定义代价函数2. 构建最小二乘问题3. 配置求解器&#xff0c;开始优化4. 优化完毕&#xff0c;查看结果 2. G2O(General Graphic Optimization)2.1 图优化2.2 具体例子2.3 C实现1. 定义顶点2. 定义边…

Redis实战(3)——缓存模型与缓存更新策略

1 什么是缓存? 缓存就是数据交换的缓冲区&#xff0c; 是存贮数据的临时区&#xff0c;一般读写性能较高 \textcolor{red}{是存贮数据的临时区&#xff0c;一般读写性能较高} 是存贮数据的临时区&#xff0c;一般读写性能较高。缓存可在多个场景下使用 以一次 w e b 请求为例…

论文总结《Neural Collaborative Filtering(NCF)》

原文链接 Neural Collaborative Filtering(NCF) Motivation 传统的矩阵分解通过latent features的内积来估计user与item的交互&#xff0c;而内积仅仅只能表示latent features的线性关系 contributions 引入MLP来替代latent features的内积&#xff0c;从而增加矩阵分解的非…

Kaggle (2) :Bike Sharing Demand 共享单车需求预测

Kaggle (2) :Bike Sharing Demand 共享单车需求预测 题目链接&#xff1a;https://www.kaggle.com/competitions/bike-sharing-demand import pandas as pd import numpy as np import seaborn as sns import matplotlib.pyplot as plt import warnings warnings.filterwarni…