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

C++ 构造函数详解

一、什么是构造函数?

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

构造函数的名字必须与类名完全相同,并且没有返回类型,甚至连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++默认给我们提供了构造函数。但是我们可以对编译器说:“不,我不想要那个默认的构造函数”

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

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

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Growthofnotes

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值