C++的四个默认函数(构造函数,析构函数,拷贝函数,赋值函数) 您所在的位置:网站首页 最小特殊符号复制函数 C++的四个默认函数(构造函数,析构函数,拷贝函数,赋值函数)

C++的四个默认函数(构造函数,析构函数,拷贝函数,赋值函数)

2024-07-13 04:58| 来源: 网络整理| 查看: 265

文章目录 一. 构造函数二. 析构函数三. 拷贝构造函数1.浅拷贝2.深拷贝 四. 赋值函数

在C++中,对于一个类,C++的编译器都会为这个类提供四个默认函数,分别是:

A() //默认构造函数 ~A() //默认析构函数 A(const A&) //默认拷贝构造函数 A& operator = (const A &) //默认赋值函数。

这四个函数如果我们不自行定义,将由编译器自动生成这四个缺省的函数,下面让我们来看看这四个函数(重点是后两个)。

一. 构造函数

构造函数是一种特殊的成员函数,与其他成员函数不同,不需要用户来调用它,而是在建立对象时自动执行。构造函数的功能是由用户定义的,用户根据初始化的要求设计函数体和函数参数,可以是一个,也可以是多个,可以把构造函数理解为重载的一种(函数名相同,不会返回任何类型,也不可以是void类型,参数类型个数可不同)。

class Animal { private: string name; public: Animal();//默认构造函数 Animal(string n);//也可以自定义构造函数 }; Animal::Animal() { //什么都不做 } Animal::Animal(string n) { this->name = n; } int main() { //第一种实例化对象的方法 Animal * a = new Animal(); //将调用默认构造函数 Animal * b = new Animal("花狗"); //将调用自定义的构造函数,对name变量初始化。 //第二种实例化对象的方法 Animal c; //将调用默认构造函数 //注意:对于无参构造函数,不可以使用Animal c(), Animal c("花狗");//将调用自定义构造函数,对name变量初始化。 return 0; }

构造函数的作用就是对当前类对象起到一个初始化的作用,类对象不像我们基本类型那样,在很多时候都需要初始化一些成员变量。

可以看到构造函数被声明在public里面,那么可以声明在private里面吗?是可以的,只不过不能被外部实例化了,在设计模式中有一种单例模式,就是这样设计的,有兴趣的可以了解一下。

二. 析构函数

与构造函数相对立的是析构函数,这个函数在对象销毁之前自动调用,例如在构造函数中,我们为成员变量申请了内存,我们就可以在析构函数中将申请的内存释放,析构函数的写法是在构造函数的基础上加一个~符号,并且只能有一个析构函数。

class Animal { private: string name; public: Animal();//默认构造函数 ~Animal(); //默认析构函数 }; 三. 拷贝构造函数 1.浅拷贝 class Animal { private: string name; public: Animal() { name = "花狗"; cout Animal a; Animal b(a); return 0; }

运行结果: 在这里插入图片描述 这个例子调用的是默认的拷贝构造函数(注意看控制台显示,调用了一次构造函数和两次析构函数),可以看出两个对象的成员变量地址是不一样的,当成员变量不存在指针类型是,这样做没什么问题,当类中有指针变量,自动生成的拷贝函数注定会出错,往下看。

2.深拷贝

我们将成员变量换成指针变量,继续实验。

class Animal { private: //string name; string * name; public: Animal() { name = new string("花狗"); cout Animal a; Animal b(a); return 0; }

运行结果: 在这里插入图片描述

可以看到两个对象的指针成员所指的内存相同(内存里面存着字符串:花狗),还记得析构函数的作用吗,在对象销毁之前自动调用,在构造函数中,我们为成员变量申请了内存,我们就可以在析构函数中将申请的内存释放。

现在在析构函数中加上对name释放的代码:

~Animal() { cout if(this !=&obj) { data=obj.data; } return *this; }

这是它的原型,类似 Animal a(b); Animal a = b; 这样的写法会调用拷贝构造函数。

而赋值函数是在当年对象已经创建之后,对该对象进行赋值的时候调用的,Animal a; a = b。

和拷贝构造函数一样,若类中有指针变量,自动生成的赋值函数注定会出错,老样子,先申请内存,再复制值即可完美解决。

Animal& operator=(const Animal&obj) { if(this !=&obj) { //默认是 name = obj.name; name = new string(*obj.name); } return *this; }

还有一个知识点就是运算符重载这一块,一个自定义类型的对象,如果想要进行预期的加减乘除之类的运算,或者是像内置类型一样,用cout输出一个类对象,这些都是需要我们来用代码告诉机器怎么做,都是需要我们来指定的。

还是拿这个类举例子,例如运算符+重载

class Animal { private: string * name; int age; int num; public: Animal() { name = new string("花狗"); age = 5; num = 4; } Animal& operator+(const Animal&obj) { if(this !=&obj) { string * s = name; name = new string(*name + *obj.name); delete s; s == NULL; this->age+=obj.age; this->num+=obj.num; } return *this; } }; int main() { Animal a; Animal b; a = a+b; //这样对象a里面的age成员的值是5,num成员的值是8,而*name的值将是"花狗花狗"; return 0; {

cout输出的定义,主要注意的是要用到友元函数。

class Animal { //中间代码略 friend ostream& operator


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有