• C++中多态中构造函数与析构函数的调用


    做个实验,看一下成员变量的构造析构,父类子类的构造析构,以及虚函数对调用的影响。

     1 #include <iostream>
     2 using namespace std;
     3 
     4 class Member
     5 {
     6 public:
     7     Member(int n):m_n1(n)
     8     {
     9         cout<<"Member::Member("<<m_n1<<")"<<endl;
    10     }
    11     ~Member()
    12     {
    13         cout<<"Member::~Member("<<m_n1<<")"<<endl;
    14     }
    15 private:
    16     const int m_n1;
    17 };
    18 
    19 class Base
    20 {
    21 public:
    22     Base():m_m1(1)
    23     {
    24         cout<<"Base::Base()"<<endl;
    25         OnConstruct();
    26     }
    27     ~Base() //这里目前不是虚函数
    28     {
    29         cout<<"Base::~Base()"<<endl;
    30         OnDistruct();
    31     }
    32     virtual void OnConstruct()
    33     {
    34         cout<<"Base::OnConstruct()"<<endl;
    35     }
    36     virtual void OnDistruct()
    37     {
    38         cout<<"Base::OnDistruct()"<<endl;
    39     }
    40     virtual void Foo1()
    41     {
    42         cout<<"Base::Foo1()"<<endl;
    43     }
    44     void Foo2()
    45     {
    46         cout<<"Base::Foo2()"<<endl;
    47     }
    48 
    49 private:
    50     Member m_m1;//这是个类对象
    51 };
    52 
    53 class Drived:public Base
    54 {
    55 public:
    56     Drived():m_m2(2)
    57     {
    58         cout<<"Drived::Drived()"<<endl;
    59         OnConstruct();
    60     }
    61     ~Drived()
    62     {
    63         cout<<"Drived::~Drived()"<<endl;
    64         OnDistruct();
    65     }
    66     virtual void OnConstruct()
    67     {
    68         cout<<"Drived::OnConstruct()"<<endl;
    69     }
    70     virtual void OnDistruct()
    71     {
    72         cout<<"Drived::OnDistruct()"<<endl;
    73     }
    74     virtual void Foo1()
    75     {
    76         cout<<"Drived::Foo1()"<<endl;
    77     }
    78     void Foo2()//这个不是虚函数
    79     {
    80         cout<<"Drived::Foo2()"<<endl;
    81     }
    82 private:
    83     Member m_m2;//这是个类对象
    84 };
    85 
    86 int main(int argc, char *argv[])
    87 {
    88     Base* p = new Drived;
    89     p->Foo1();
    90     p->Foo2();
    91     delete p;
    92     return 0;
    93 }

    这段代码的运行输出为:

     1 Member::Member(1)  //父类的初始化列表被执行
     2 Base::Base()       //父类构造
     3 Base::OnConstruct()//父类构造中只会调用父类的函数。父类构造完毕
     4 Member::Member(2)    //子类构造的初始化列表
     5 Drived::Drived()     //子类构造
     6 Drived::OnConstruct()//子类构造中只会调用子类的函数。子类构造完毕
     7 Drived::Foo1()//发生多态,调用子类重写的函数
     8 Base::Foo2()  //未多态,调用父类版本的函数
     9 Base::~Base()     //父类开始析构
    10 Base::OnDistruct()//父类析构只会调用父类中的函数
    11 Member::~Member(1)//父类成员反初始化

    同学们可以看到,子类的析构没有被执行,怎么让它能值执行呢?把父类的析构修饰为virtual即可:

    27     ~Base() //这里目前不是虚函数

    这样在执行一遍,可以看到结果如果(注释出来的是新增的输出):

     1 Member::Member(1)
     2 Base::Base()
     3 Base::OnConstruct()
     4 Member::Member(2)
     5 Drived::Drived()
     6 Drived::OnConstruct()
     7 Drived::Foo1()
     8 Base::Foo2()
     9 Drived::~Drived()   //子类析构,在父类之前执行
    10 Drived::OnDistruct()//子类析构只会调用子类的函数
    11 Member::~Member(2)  //子类成员反初始化
    12 Base::~Base()
    13 Base::OnDistruct()
    14 Member::~Member(1)

     小结一下:

    通过父类指针指向子类对象实现多态。

    多态的时候,父类析构修饰为虚函数,以保证子类析构被调用。

    构造顺序是:先父类后子类(这是最主要流程,后两条都再此前提下);初始化列表在构造前执行;构造函数中值调用本类的函数(无论是否为虚函数)。

    析构顺序是:先子类后父类(注意虚析构);析构中只调用本类的函数;本类析构后再析构初始化列表中的成员。

    
    
  • 相关阅读:
    js定时跳转
    MySQL跨表更新字段 工作记录
    windows下安装phpcms html/ 文件夹不可写的一种错误以及解决方法
    linux清理僵尸进程
    JQuery实现隔行变色和突出显示当前行 效果
    windows下配置lamp环境(4)---安装MySQL数据库5.6
    windows下配置lamp环境(5)---配置MySQL5.6
    windows下配置lamp环境(3)---配置PHP5.4
    windows下配置lamp环境(0)---软件获取
    windows下配置lamp环境(2)---配置Apache服务器2.2.25
  • 原文地址:https://www.cnblogs.com/zhaojk2010/p/4649269.html
Copyright © 2020-2023  润新知