C++—21、C++ 中构造函数Constructors

embedded/2025/1/24 14:33:41/

一、什么是构造函数?

构造函数是一个特殊的方法,它在类每次实例化创建对象的时侯自动调用,用于初始化对象。

构造函数的名字必须与类名完全相同,并且没有返回类型,甚至连void也没有。

构造函数的目的是确保对象在创建时处于一个有效的、已知的状态。

二、构造函数存在的原因探讨:

1、假设我们要建一个Entity类,里面有位置信息,我们实例化后,打印出来,如下所示:

运行代码,打印出来一些随机值。

这是因为当我们实例化Entity类并且分配内存的时候,但实际上还没有对内存进行初始化,就是说内存空间还是原来的内容。

我们想做的可能就是初始化内存并把它设置为0,这样我们的位置默认就是0,而我们并不用显示的去指定一个值。

2、如果我们想手动打印X和Y,因为它们是公有的,所以我可以使用e.X直接把X打印出来。如下:

这里出现了错误,说使用未初始化的内存e和未初始化的局部变量(uninitialized local variable)e的报错信息。

换句话说,这个代码都不能通过编译,因为我们在尝试使用未初始化的内存。

上一个print函数仍然可以通过编译。但是它并没有像我们期望的那样运行,当然这是因为它在打印X和Y时被设置成随机值。

3、归纳一下

我们已经知道要做的就是需要做某种初始化。我们需要某种在我们创建Entity实例的时候就会自动把X和Y设置为0的方法,除非我们想设置为特定的值。

可能你想做的就是创建一个初始化方法。因此我们来创建一个Init方法,它的工作就是设置X和Y的值为0.

现在我能做的就是当我创建Entity的时候,调用e.Init()。然后调用print()方法尝试进行打印。

但是这样我们添加了太多的代码,我们必须定义这个Init方法,然后每当我要创建一个Enity的时候我都必须要去调用Init函数,这代码非常冗余而且一点也不清爽。如果当我们创建Entity的时候能自动运行这个初始化方法就好了,每当你创建一个对象的时候它就会被调用。

三、构造函数的定义

1、‌默认构造函数‌:

没有参数的构造函数。如果类中没有定义任何构造函数,编译器会自动生成一个默认构造函数。如果定义了其他构造函数,编译器则不会自动生成默认构造函数。

class MyClass {
public:MyClass() {// 初始化代码}
};

在Java中,基本数据类型中,比如int和float类型会默认被初始化为0,但是c++中不是这样的,你必须手动初始化所有的基本类型,不然,它们就会被设置为之前留存在内存中的值,所以非常非常重要的是,不要忘记进行初始化。还是那样,我会在以后讲解更多关于初始化和正确初始化的策略和方法。

2、参数化构造函数‌:接受一个或多个参数的构造函数。 


      让我们来看看带参数的构造函数,我门可以写多个构造函数,但是要给他们提供不同的参数,这个我写同名方法是一样的。其实这叫函数重载,就是相同的函数名有不同的参数的不同版本函数,我把x和y作为参数添加到这里,然后把x和y赋值给X和Y。

#include <iostream>class Entity
{
public:float X,Y;//用来表示Entity的位置;Entity(){X = 0.0f;Y = 0.0f;}Entity(float x,float y){X = x;Y = y;}void Print()//把位置输出到控制台{std::cout << X <<"," << Y << std::endl;}};int main()
{Entity e(10.0f,5.0f);//创建Entity的实例,e.Print();//调用print函数,运行函数
}

运行结果如下:

3、‌拷贝构造函数‌:用于创建一个对象作为另一个同类型对象的副本。

拷贝构造函数接受一个同类型对象的常量引用作为参数。如果类中没有定义拷贝构造函数,编译器会自动生成一个默认的拷贝构造函数。

class MyClass {
private:int* data;
public:MyClass(const MyClass& other) {// 深度拷贝代码data = new int(*other.data);}
};

4、移动构造函数‌(C++11及以后):用于“窃取”另一个对象的资源而不是复制它们,以提高效率。

移动构造函数接受一个同类型对象的右值引用作为参数。

class MyClass {
private:int* data;
public:MyClass(MyClass&& other) noexcept {data = other.data;other.data = nullptr; // 防止析构时释放资源}
};

四、注意事项

构造函数不会在你没有实例化对象的时候运行,所以如果你只是使用类的静态方法,构造函数是不会执行的。当你用new关键字创建对象实例的时候也会调用构造函数。

也有一些方法可以删除构造函数,比如说你有一个只有静态方法的Log类,就像这里的static void Log()。

我想让别人只像这样使用这个Log类,不希望别人创建实例。有两种不同的解决方法,我们可以通过设置private来隐藏构造函数。

运行你会发现,报错了,因为我不能访问构造函数。

如果不添加

private:
    Log()
    {

    }

你可以看到显然是允许构造函数构造这个对象的。

因为c++默认给我们提供了构造函数。但是我们可以对编译器说:“不,我不想要那个默认的构造函数”

这里,我们就无法调用,因为默认构造函数已经不存在了,被删除了。

还有一些特殊类型的构造函数,比如说赋值构造函数和移动构造函数。他们都比较复杂,需要单独介绍。

构造函数是一个特殊的函数,会在你每次实例化类的时候调用,最主要的用处就是来初始化类

。当你创建一个对象实例的时候,确保你初始化了所有的内存和做了所有你需要的设置。


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

相关文章

C语言初阶牛客网刷题——HJ73 计算日期到天数转换【难度:简单】

1. 题目描述——HJ73 计算日期到天数转换 牛客网OJ题链接 描述 每一年中都有 12 个月份。其中&#xff0c;1,3,5,7,8,10,12 月每个月有 31 天&#xff1b; 4,6,9,11 月每个月有 30 天&#xff1b;而对于 2 月&#xff0c;闰年时有29 天&#xff0c;平年时有 28 天。 现在&am…

Android节点读写实现

在工作中&#xff0c;我们会对一些节点进行读写操作。比如控制闪光灯&#xff0c;指示灯;降噪芯片开关或其低功耗开关&#xff0c;因为项目中常用到&#xff0c;在此记录&#xff0c;备忘&#xff5e; 直接上代码&#xff0c;想用直接拿去 一 监听某个节点的写入值的反馈 有些…

python将txt文件转成csv文件

1.才开始使用Jupyter Notebook,发现用此软件做些实践性的工作还是非常方便的,在此强烈推荐 2)网上下个txt文本文件,为了想做后续词云统计方便,果断转换为csv,代码如下: import csv data[] with open(C:\\Users\\Administrator\\Desktop\\修行大智慧\\《道德经》原文全文&#…

大数据技术笔记

大数据技术概述 本章初步介绍大数据领域技术涉及的一些基础理论&#xff0c;如分布式、存储、网络等知识。 分布式理论 大数据意味数据量大&#xff0c;那么存储和计算数据的节点就不大可能只有一个&#xff0c;而是采用分而治之的思想在多个节点中存储和计算&#xff0c;提…

springboot图书馆管理系统前后端分离版本

springboot图书馆管理系统前后端分离版本, 系统供的功能全部都可以使用 这是一个成品,系统的架构包括代码的层次都比较清晰而且功能比较丰富大家可以拿到手里改改界面改改文字的描述细节稍微修改一下就可以完成自己的毕业设计了,也可二次开发 系统特性 技术先进:使用了最新…

Frida使用指南(三)

当需要输出其他格式的数据时: Java.perform(function () {var SignManager = Java.use("com.che168.atclibrary.base.SignManager");

Git Bash 配置 zsh

博客食用更佳 博客链接 安装 zsh 安装 Zsh 安装 Oh-my-zsh github仓库 sh -c "$(curl -fsSL https://install.ohmyz.sh/)"让 zsh 成为 git bash 默认终端 vi ~/.bashrc写入&#xff1a; if [ -t 1 ]; thenexec zsh fisource ~/.bashrc再重启即可。 更换主题 …

【LeetCode】--- MySQL刷题集合

1.组合两个表&#xff08;外连接&#xff09; select p.firstName,p.lastName,a.city,a.state from Person p left join Address a on p.personId a.personId; 以左边表为基准&#xff0c;去连接右边的表。取两表的交集和左表的全集 2.第二高的薪水 &#xff08;子查询、if…