构造函数与析构函数

来源:互联网 发布:谷歌 云计算 编辑:程序博客网 时间:2024/06/17 22:05

这个题目略大,所以不说基础的东西,说下面试中常提到的问题

1.构造函数和析构函数调用顺序问题

对于同一类的不同对象


例子:
class A{    public:A(){}~A(){}};A a1,a2

先调用a1构造函数,再调用a2的构造函数,然后调用a2的析构函数,最后调用a1的析构函数

好,这是对于同一类的不同对象

那基类和派生类的顺序呢

两个问题:
1)派生类构造函数初始化成员时的顺序,是先基类然后派生,还是先将派生的成员初始化然后基类成员
2)析构函数是先析构派生类的派生成员后基类中的成员,还是反过来

第一个问题,先初始化基类的成员,即先调用基类构造函数,然后初始化派生成员,即派生类构造函数本身,在运用参数初始化列表是,也是这个顺序
对于多层派生,派生类只调用它的直接父类,而不需要,逐层去显示调用。
第二个问题,在派生时,派生类是不能继承基类的析构函数的,需要通过派生类的析构函数去调用基类的析构函数,过程正好跟构造的过程相反

2.构造函数能是虚函数么,为什么?

这个问题在面试中经常被问到,首先这样回答:构造函数不能是虚函数,也不需要是虚函数。

具体的解释如下:

1)从用途来看,构造函数是用来初始化对象具体实例的,既要实例化基类数据成员也要初始化派生数据成员,而虚函数的用途呢,是在接口复用是,能够实现基类指针能够访问指定的派生类方法函数。由此可见构造函数本身就是要初始化实例,那使用虚函数也没有实际意义呀。所以构造函数没有必要是虚函数。虚函数的作用在于通过父类的指针或者引用来调用它的时候能够变成调用子类的那个成员函数。而构造函数是在创建对象时自动调用的,不可能通过父类的指针或者引用去调用,因此也就规定构造函数不能是虚函数。

2)存储角度来说,每一个类都会维护一张vptr表,用来存储虚函数的入口地址,如果构造函数是虚函数,造成了不必要的开销

3)从实现上看,如果构造函数是虚函数,在初始化实例时由于对象还未构造成功,编译器无法知道对象 的实际类型,是该类本身,还是该类的一个派生类,或是更深层次的派生类。无法确定。当然还有vbtl在构造函数调用后才建立,因而构造函数不可能成为虚函数 

4)从代码编写的容错上来看,如果你在子类中一不小心重写了个跟父类构造函数一样的函数,那么你的父类的构造函数将被覆盖,也即不能完成父类的构造.就会出错


3.析构函数被声明为虚函数的好处?

1)在基类中将析构函数申明为虚函数,可以保证在之后的派生类中,以及派生类之后的派生类中的虚函数都为虚函数
2)能够避免通过基类指针调用派生类方法,而派生类对象是动态分配(new)出来的时候,只调用基类的构造函数而不调用派生类的构造函数的情况。

3)析构函数可以是纯虚函数






0 0