C++中多态中构造函数与析构函数的调用
做个实验,看一下成员变量的构造析构,父类子类的构造析构,以及虚函数对调用的影响。
#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()
{
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()
{
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 ;
}
这段代码的运行输出为:
Member::Member() //父类的初始化列表被执行
Base::Base() //父类构造
Base::OnConstruct()//父类构造中只会调用父类的函数。父类构造完毕
Member::Member() //子类构造的初始化列表
Drived::Drived() //子类构造
Drived::OnConstruct()//子类构造中只会调用子类的函数。子类构造完毕
Drived::Foo1()//发生多态,调用子类重写的函数
Base::Foo2() //未多态,调用父类版本的函数
Base::~Base() //父类开始析构
Base::OnDistruct()//父类析构只会调用父类中的函数
Member::~Member()//父类成员反初始化
同学们可以看到,子类的析构没有被执行,怎么让它能值执行呢?把父类的析构修饰为virtual即可:
~Base() //这里目前不是虚函数
这样在执行一遍,可以看到结果如果(注释出来的是新增的输出):
Member::Member()
Base::Base()
Base::OnConstruct()
Member::Member()
Drived::Drived()
Drived::OnConstruct()
Drived::Foo1()
Base::Foo2()
Drived::~Drived() //子类析构,在父类之前执行
Drived::OnDistruct()//子类析构只会调用子类的函数
Member::~Member() //子类成员反初始化
Base::~Base()
Base::OnDistruct()
Member::~Member()
小结一下:
通过父类指针指向子类对象实现多态。
多态的时候,父类析构修饰为虚函数,以保证子类析构被调用。
构造顺序是:先父类后子类(这是最主要流程,后两条都再此前提下);初始化列表在构造前执行;构造函数中值调用本类的函数(无论是否为虚函数)。
析构顺序是:先子类后父类(注意虚析构);析构中只调用本类的函数;本类析构后再析构初始化列表中的成员。
C++中多态中构造函数与析构函数的调用的更多相关文章
- C++C++中构造函数与析构函数的调用顺序
http://blog.csdn.net/xw13106209/article/details/6899370 1.参考文献 参考1: C++继承中构造函数.析构函数调用顺序及虚函数的动态绑定 参考2 ...
- C++中构造函数和析构函数的调用顺序
一般而言,析构函数调用的顺序和构造函数调用顺序相反,但是,对象的存储类别可以改变调用析构函数的顺序.举例说明: CreateAndDestroy类的定义 CreateAndDestroy类的成员函数的 ...
- C++学习笔记(7)----类的数组中构造函数和析构函数的调用顺序
C++类的数组中构造函数和析构函数的调用顺序(2) 对于如下的代码: #include<iostream> using namespace std; class CBase { priva ...
- C++ 构造函数和析构函数的调用顺序、虚析构函数的作用
构造函数和析构函数的调用顺序 构造函数的调用顺序: 当建立一个对象时,首先调用基类的构造函数,然后调用下一个派生类的构造函数,依次类推,直至到达最底层的目标派生类的构造函数为止. 析构函数的调用书序: ...
- C++类中函数(构造函数、析构函数、拷贝构造函数、赋值构造函数)
[1]为什么空类可以创建对象呢? 示例代码如下: #include <iostream> using namespace std; class Empty { }; void main() ...
- C++中:默认构造函数、析构函数、拷贝构造函数和赋值函数——转
对于一个空类,编译器默认产生4个成员函数:默认构造函数.析构函数.拷贝构造函数和赋值函数.1.构造函数:构造函数是一种特殊的类成员,是当创建一个类的时候,它被调用来对类的数据成员进行初始化和分配内存. ...
- C++继承,多重继承,虚继承的构造函数以及析构函数的调用顺序问题
#include <iostream> using namespace std; class A{ int data_a; public: A(){ data_a = ; cout < ...
- C++:派生类的构造函数和析构函数的调用顺序
一.派生类 在C++编程中,我们在编写一个基类的派生类时,大致可以分为四步: • 吸收基类的成员:不论是数据成员还是函数成员,派生类吸收除基类的构造函数和析构函数之外的全部成员. • 改造基类函数:在 ...
- 【C++】不要在构造函数或析构函数内调用虚函数
这个问题来自于<Effective C++>条款9:永远不要在构造函数或析构函数中调用虚函数 . 假设有如下代码: class Transaction {// 所有交易的基类 public ...
- C++构造函数和析构函数的调用顺序
1.构造函数的调用顺序 基类构造函数.对象成员构造函数.派生类本身的构造函数 2.析构函数的调用顺序 派生类本身的析构函数.对象成员析构函数.基类析构函数(与构造顺序正好相反) 3.特例 局部对象,在 ...
随机推荐
- quartz里job不执行的解决方案(并发量太低原因)
这里写链接内容 使用框架spring3+quartz1.8 生产环境中碰到会有job一直不执行的情况,后来分析是因为quartz中线程总数太少,而项目中所有的job都是并发执行的就会导致当到达时间节点 ...
- servlet.xml 出现 Referenced file contains errors(http://.......)
问题描述: 打开Eclipse突然发现Web工程的servlet.xml突然报了红叉叉,错误信息如下: Referenced file contains errors (http://www.spri ...
- PAT 乙级 1031 查验身份证(15) C++版
1031. 查验身份证(15) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CHEN, Yue 一个合法的身份证号码由17位地区. ...
- QLExpress 规则引擎使用介绍
一个轻量级的类java语法规则引擎,作为一个嵌入式规则引擎在业务系统中使用.让业务规则定义简便而不失灵活.让业务人员就可以定义业务规则.支持标准的JAVA语法,还可以支持自定义操作符号.操作符号重载. ...
- K近邻(K Nearest Neighbor-KNN)原理讲解及实现
算法原理 K最近邻(k-Nearest Neighbor)算法是比较简单的机器学习算法.它采用测量不同特征值之间的距离方法进行分类.它的思想很简单:如果一个样本在特征空间中的k个最近邻(最相似)的样本 ...
- Android-PullToRefresh 下拉刷新增加setOnItemLongClickListener
项目地址:https://github.com/chrisbanes/Android-PullToRefresh 不知道为什么这个项目没有给listview 加 OnItemLongClickLis ...
- centos6.8下pptp客户端的安装配置
原文: https://blog.csdn.net/zhang11321132/article/details/20612473 yum -y install ppp pptp pptp-setup ...
- XHR HTTP 请求 get post请求解决方案
XHR请求的 测试方式, postman 64位下载地址: http://www.downza.cn/download?file=2017%2F01%2FPostmanwin64493.zip& ...
- Jmeter(八)HTTPCookie管理器
Cookie绝对是日常工作以及技术中一个绕不过去的‘角色’,正常各种各样的业务需要Cookie的存在.Jmeter中也有支持发送Cookie的组件,但是,仅是后话:在此还是有必要先记一记Cookie到 ...
- [UE4]更新Flag坐标
UserWidget中也是有Event Tick事件,游戏运行每一帧都会调用这个事件 一.在MiniMapFlagData结构体中,添加Slot和ImageWidget变量 二.在StaticMini ...