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

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
结果无需继续解释。

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

发布了11 篇原创文章 · 获赞 1 · 访问量 1万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览