您的位置:首页 > 编程语言 > C语言/C++

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

2015-07-15 18:59 489 查看
做个实验,看一下成员变量的构造析构,父类子类的构造析构,以及虚函数对调用的影响。

#include <iostream>
using namespace std;

class Member
{
public:
Member(int n):m_n1(n)
{
cout<<"Member::Member("<<m_n1<<")"<<endl;
}
~Member()
{
cout<<"Member::~Member("<<m_n1<<")"<<endl;
}
private:
const int m_n1;
};

class Base
{
public:
Base():m_m1(1)
{
cout<<"Base::Base()"<<endl;
OnConstruct();
}
~Base() //这里目前不是虚函数
{
cout<<"Base::~Base()"<<endl;
OnDistruct();
}
virtual void OnConstruct()
{
cout<<"Base::OnConstruct()"<<endl;
}
virtual void OnDistruct()
{
cout<<"Base::OnDistruct()"<<endl;
}
virtual void Foo1()
{
cout<<"Base::Foo1()"<<endl;
}
void Foo2()
{
cout<<"Base::Foo2()"<<endl;
}

private:
Member m_m1;//这是个类对象
};

class Drived:public Base
{
public:
Drived():m_m2(2)
{
cout<<"Drived::Drived()"<<endl;
OnConstruct();
}
~Drived()
{
cout<<"Drived::~Drived()"<<endl;
OnDistruct();
}
virtual void OnConstruct()
{
cout<<"Drived::OnConstruct()"<<endl;
}
virtual void OnDistruct()
{
cout<<"Drived::OnDistruct()"<<endl;
}
virtual void Foo1()
{
cout<<"Drived::Foo1()"<<endl;
}
void Foo2()//这个不是虚函数
{
cout<<"Drived::Foo2()"<<endl;
}
private:
Member m_m2;//这是个类对象
};

int main(int argc, char *argv[])
{
Base* p = new Drived;
p->Foo1();
p->Foo2();
delete p;
return 0;
}


这段代码的运行输出为:

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


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

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


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

Member::Member(1)
Base::Base()
Base::OnConstruct()
Member::Member(2)
Drived::Drived()
Drived::OnConstruct()
Drived::Foo1()
Base::Foo2()
Drived::~Drived()   //子类析构,在父类之前执行
Drived::OnDistruct()//子类析构只会调用子类的函数
Member::~Member(2)  //子类成员反初始化
Base::~Base()
Base::OnDistruct()
Member::~Member(1)


小结一下:

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

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

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

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


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: