构造函数与析构函数执行顺序及其与虚函数关系

来源:互联网 发布:软件测试的工资待遇 编辑:程序博客网 时间:2024/06/06 19:11

1.构造函数与析构函数执行顺序:

(1) 继承类首先从基类构造函数开始执行,然后调用成员对象的构造函数,最后调用自己的构造函数(中间可能存在多个层次),;

(2)析构函数的执行顺序与构造函数相反,析构函数调用之后会调用成员对象的析构函数;

(3)成员对象的构造顺序是声明顺序,不是构造函数的初始化列表顺序,这样可以保证顺序的唯一性。

(4) 局部对象在程序结束或函数退出时会自动调用析构函数,但是分配在堆中的对象(new)不会,除非显示调用delete。

借用代码说明:

#include <iostream>#include <string>#include <stdlib.h>#include <stdio.h>#include <string.h>using namespace::std;class C{        public:                C() {cout<<"C";}                ~C(){cout<<"~C";}};class A{        public:                A() {cout<<"A";}                ~A(){cout<<"~A";}};class B : public A{        public:                //B(A &a, C &c):_a(a), _c(c) {cout<<"B";}                B() {cout<<"B";}                ~B(){cout<<"~B";}        private:                C _c;                A _a;};int main(int argc, char**argv){        //C *d=new C();        //A *e=new A();        C c;        A a;        //B b(a, c);        //B b(*d, *e);        B b;        return 0;}


输出结果为:CAACAB~B~A~C~A~A~C

构造c和a输出CA,B从基类A开始构造输出A,然后是其成员对象_c和_a按照声明顺序构造CA(如果调整声明顺序会发现输出顺序相反),然后调用B自身的构造函数。

main函数退出,析构局部对象,从B开始首先B的析构函数~B,然后成员对象_c和_a,析构顺序与声明顺序相反~A~C(如果调整声明顺序会发现输出顺序相反),然后B的基类调用析构函数~A,然后a和c分别调用析构函数~A~C。

如果main函数使用对象d和e(注释a和c),因为是分配在堆中,所以函数退出时候不会释放d和e,即不会调用析构函数,输出结果变为CAACAB~B~A~C~A。

同时,如果B的构造函数采用注释行的方式(main函数中b使用B b(a, c)),对象_a和_c的赋值方式是采用拷贝函数,不会调用构造函数,因此会少输出CA一次,输出结果为CAAB~B~C~A~A~A~C。但是在对象已经建立,因此在析构的时候,析构函数照常调用。


2. 虚函数与构造函数和析构函数 

(1) 构造函数本身不能是虚拟函数;并且虚机制在构造函数中不起作用(在构造函数中的虚拟函数只会调用它的本地版本)。

(2) 析构函数本身常常要求是虚拟函数;但虚机制在析构函数中不起作用,因为可能会引起调用已经被delete掉的类的虚拟函数的问题。

(3) 若类中使用了虚拟函数,析构函数一定要是虚拟函数,比如使用虚拟机制调用delete,没有虚拟的析构函数,不能保证delete的是你希望delete的对象。
代码说明:
#include <iostream>#include <stdio.h>using namespace::std;class Base{        public:                Base()                {                        init();                }                virtual void init()                {                        printf("init base\n");                }};class Super : public Base{        public:                Super()                {                        init();                }                virtual void init()                {                        printf("init super\n");                }};int main(int argc, char**argv){        Base *ptr=new Super();        return 0;}

输出结果为:
init base
init super
结果无需继续解释。

如有错误,谢谢指出更正!

原创粉丝点击