200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > C++——构造函数 析构函数以及复制构造函数

C++——构造函数 析构函数以及复制构造函数

时间:2020-02-18 09:05:45

相关推荐

C++——构造函数 析构函数以及复制构造函数

文章目录

一、构造函数1.1 构造函数是什么?1.2 为什么要有构造函数?1.3 如何使用构造函数?1.4 构造函数的实现二、复制构造函数2.1 什么是复制构造函数?2.2 为什么要有复制构造函数?2.3 复制构造函数的功能三、析构函数什么是析构函数?

一、构造函数

在程序执行的过程中,当遇到与对声明语句时,程序会向操作系统申请一定的内存空间用于存放新建的对象。但是与普通变量相比,类的对象特别复杂,编译器不知如何产生代码去初始化对象,这便引出了构造函数。

1.1 构造函数是什么?

C++中,构造函数是一种特殊的成员函数,在每次创建一个类的时候编译器都会默认调用构造函数进行初始化。

1.2 为什么要有构造函数?

构造函数的作用就是在对象被创建的时候,利用特定的值构造对象,将对象初始化为一个特定的状态。

1.3 如何使用构造函数?

要学会如何使用构造函数,首先需要了解构造函数的一些特殊性质:构造函数的函数名与类名相同,而且没有返回值;构造函数通常被声明为公有函数。

Notes:只要类中有了构造函数,编译器就会在创建新对象的地方自动插入对构造函数调用的代码。所以构造函数在对象被创建的时候将会被自动调用。

下面分别介绍常见的几种构造函数:

默认构造函数:

class Clock{public:Clock() //编译器自动生成的隐含的默认构造函数;{}....};

默认构造函数调用时无须提供参数。如果类中没有写构造函数,那么编译器会自动生成一个隐含的默认构造参数,该构造函数的参数列表和函数体都为空,这个构造函数不做任何事情。

Notes: 无参数的构造函数与全缺省的构造函数都称为默认构造函数。

Q:既然默认构造函数不做任何事情,那么为什么还要生成这个构造函数?

答:因为在建立对象时自动调用构造函数时C++必然要做的事情。上述例子中,默认构造函数什么都没有做,但是有些函数体为空的构造函数并非什么都不做,因为它还要负责基类的构造和成员对象的构造。

有参数的构造函数和无参数的构造函数

class Clock{public:Clock(int NewH,int NewM,int NewS); //有参数的构造函数Clock() //无参数的构造函数{hour = 0;minute = 0;second = 0;}void SetTime(int NewH,int NewM,int NewS);void ShowTime();private:int hour,minute,second;};int main(){Clock(0,0,0); //调用有参数的构造函数Clock my_clock; //调用无参数的构造函数return 0;}

上述例子中出现了两种重载的构造函数的形式:有参数的和无参数的(即默认构造函数)

1.4 构造函数的实现

Clock::Clock(int NewH, int NewM, int NewS) {hour = NewH;minute = NewM;second = NewS;}

二、复制构造函数

生成一个对象的副本有两种途径,第一种途径是建立一个新的对象,然后将原始对象的数据成员取出来,赋值给新对象。这样做显然太繁琐了,所以为了使得一个类具有自行复制本类对象的能力,复制构造函数被引出。

2.1 什么是复制构造函数?

复制构造函数是一种特殊的构造函数,其具有一般构造函数的所有特性,其形参是本类对象的引用。

2.2 为什么要有复制构造函数?

复制构造函数的作用是使得一个已经存在的对象(由复制构造函数的参数指定),去初始化一个同类的一个新对象。如果程序没有定义类的复制构造函数,系统就会在必要时自动生成一个隐藏的复制构造函数。这个隐藏的复制构造函数的功能是,把初始值对象的每个数据成员复制到新建立的对象中去。这样得到的对象和原本的对象具有相同的数据成员和属性。

2.3 复制构造函数的功能

在说明复制构造函数的功能之前,我们先看一下声明和实现复制构造函数的一般方法:

class 类名{public:类名(形参); //构造函数类名(类名& 对象名); //复制构造函数...};类名::类名(类名 &对象名) //复制构造函数的实现{//函数体}

前面我们知道,普通的构造函数在对象被创建的时候调用,而复制构造函数在下面3种情况下均会被调用:

例:

class Point{public:Point(int x = 0,int y = 0){_x = x;_y = y;}Point(Point& p); //复制构造函数int GetX(){return _x;}int GetY(){return _y;}private:int _x,_y;};

当用类的一个对象去初始化另一个对象时:

int main(){Point a(1,2);Point b(a); //用对象a初始化对象b时,复制构造函数被调用Point c = a; //用对象a初始化对象c时,复制构造函数被调用return 0;}

Notes:上面对b和c的初始化都能够调用复制构造函数,两种写法是等价的,执行的操作完全相同。

如果函数的形参是类的对象,调用函数时,进行形参和实参结合时:

void Fun(Point p){//函数体}int main(){Point a(1,2);Fun(a); //函数的形参为类的对象,当调用对象时,复制构造函数被调用.return 0;}

Notes:只有把对象用值传递的时候,才会调用复制构造函数。如果传递的是引用,则不会调用复制构造函数。所以这也是传递引用会比传值的效率高的原因。

如果函数的返回值是类的对象,函数执行完成返回调用者时:

Point Fun(){Point a(1,2);return a; //函数Fun的返回值是类的对象,返回函数值的时候,调用复制构造函数}int main(){Point b;b = Fun();return 0;}

Q:为什么在这种情况下,返回函数值的时候会调用复制构造函数?

答:函数Fun()将a返回给了主函数,但是我们都知道a是Fun()的局部变量,当Fun()函数的生命周期结束的时候,a也就消亡了,不可能在返回主函数后继续生存。所以在这种情况下编译器会在主函数中创建一个无名的临时对象,该临时对象的生命周期仅仅在b = Fun()中。当执行语句return a时,实际上是调用复制构造函数将a的值复制到无名临时对象中。当函数Fun()运行结束时,对象a消失,但是临时对象会存在于b = Fun()中。当计算这个表达式后,临时对象也就完成了它的工作。

三、析构函数

我们刚讨论了当一个局部变量随着它的函数生命周期结束的时候,函数中的对象也会消失,那么在对象,要消失的时候(比如构造对象的时候,在函数中用malloc动态申请了空间)谁来做这些所谓的“善后”工作呢?这样我们就引出了析构函数。

什么是析构函数?

与构造函数一样,析构函数通常也是类的一个公有成员函数,它的名称是由类名前面加一个"~"构成,没有返回值。析构函数与构造函数不同的是,析构函数不接受任何参数!(参数可以是虚函数),如果我们不自行定义析构函数,则编译器同样会自动生成一个隐藏的析构函数,它的函数体为空。

下面我们看一下析构函数的声明:

class Clock{public:Clock(int NewH,int NewM,int NewS); //有参数的构造函数Clock() //无参数的构造函数{hour = 0;minute = 0;second = 0;}void SetTime(int NewH,int NewM,int NewS);void ShowTime();~Clock(); //析构函数private:int hour,minute,second;};

Notes:函数体为空的析构函数并不是什么都不做。

Tips:

类的构造顺序是按照语句的顺序进行构造

类的析构函数调用完全按照构造函数调用的相反顺序进行调用

1.全局对象先于局部对象进行构造

2.静态对象先于普通对象进行构造

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。