构造函数

   先看看构造函数的调用顺序规则,只要我们在平时编程的时候遵守这种约定,任何关于构造函数的调用问题都能解决;构造函数的调用顺序总是如下:
1.基类构造函数。如果有多个基类,则构造函数的调用顺序是某类在类派生表中出现的顺序,而不是它们在成员初始化表中的顺序。
2.成员类对象构造函数。如果有多个成员类对象则构造函数的调用顺序是对象在类中被声明的顺序,而不是它们出现在成员初始化表中的顺序。
3.派生类构造函数。

析构函数
    析构函数的调用顺序与构造函数的调用顺序正好相反,将上面3个点反过来用就可以了,首先调用派生类的析构函数;其次再调用成员类对象的析构函数;最后调用基类的析构函数。
    析构函数在下边3种情况时被调用:
    1.对象生命周期结束,被销毁时(一般类成员的指针变量与引用都i不自动调用析构函数);
    2.delete指向对象的指针时,或delete指向对象的基类类型指针,而其基类虚构函数是虚函数时;
    3.对象i是对象o的成员,o的析构函数被调用时,对象i的析构函数也被调用。

virtual析构函数
下面来说一说为多态基类声明virtual析构函数:
在C++中,构造函数不能声时为虚函数,这是因为编译器在构造对象时,必须知道确切类型,才能正确的生成对象,因此,不允许使用动态束定;其次,在构造函数执行之前,对象并不存在,无法使用指向此此对象的指针来调用构造函数,然而,析构函数是可以声明为虚函数;C++明白指出,当derived class对象经由一个base class指针被删除,而该base class带着一个non-virtual析构函数,其结果未有定义---实际执行时通常发生的是对象的derived成分没被销毁掉。

class Derive:public Base
{
public:
    Derive(){ std::cout<<"Derive::Derive()"<<std::endl; }
    ~Derive(){ std::cout<<"Derive::~Derive()"<<std::endl; }
};

int _tmain(int argc, _TCHAR* argv[])
{
    Base* pBase = new Derive();
    delete pBase;

return 0;
}

输出结果是:
Base::Base()
Derive::Derive()
Derive::~Derive()
Base::~Base()

由结果可以看出,在父类的虚析构函数有自己的实现时,当调用完子类对象的析构函数结束后,还会调用父类的析构函数。而一般的虚函数都是子类覆盖了父类的,调用完子类方法后不会再调用父类的方法。况且虚析构函数也不能想一般的虚函数一样写成纯虚函数的形式。这一切还是由于析构函数的特殊性决定的。

构造和析构函数都有着特别的意义,这是与其它函数不同的,并且在一个类层次中析构函数都会被调用,并且调用顺序是有规定的(文章开头已讲),这些是编译器决定的。因此我们必须给出虚析构函数的函数体以供调用。既然调用顺序已定,父类对象的析构函数总是会被调用,所以就没有被子类覆盖之说了。

C++构造函数和析构函数顺序的更多相关文章

  1. C++C++中构造函数与析构函数的调用顺序

    http://blog.csdn.net/xw13106209/article/details/6899370 1.参考文献 参考1: C++继承中构造函数.析构函数调用顺序及虚函数的动态绑定 参考2 ...

  2. C++-理解构造函数、析构函数执行顺序

    先初始化序列中的函数调用,如果基类构造函数为非引用传递,则引起参数的拷贝构造 再: 先类内的成员构造函数(拷贝/默认),再类的构造函数:先基类,再派生类: 本文主要说明对象创建时构造函数的执行顺序,对 ...

  3. C++ 构造函数和析构函数的调用顺序、虚析构函数的作用

    构造函数和析构函数的调用顺序 构造函数的调用顺序: 当建立一个对象时,首先调用基类的构造函数,然后调用下一个派生类的构造函数,依次类推,直至到达最底层的目标派生类的构造函数为止. 析构函数的调用书序: ...

  4. C++构造函数和析构函数的调用顺序

    1.构造函数的调用顺序 基类构造函数.对象成员构造函数.派生类本身的构造函数 2.析构函数的调用顺序 派生类本身的析构函数.对象成员析构函数.基类析构函数(与构造顺序正好相反) 3.特例 局部对象,在 ...

  5. C++中构造函数和析构函数的调用顺序

    一般而言,析构函数调用的顺序和构造函数调用顺序相反,但是,对象的存储类别可以改变调用析构函数的顺序.举例说明: CreateAndDestroy类的定义 CreateAndDestroy类的成员函数的 ...

  6. C++:派生类的构造函数和析构函数的调用顺序

    一.派生类 在C++编程中,我们在编写一个基类的派生类时,大致可以分为四步: • 吸收基类的成员:不论是数据成员还是函数成员,派生类吸收除基类的构造函数和析构函数之外的全部成员. • 改造基类函数:在 ...

  7. C++学习笔记(7)----类的数组中构造函数和析构函数的调用顺序

    C++类的数组中构造函数和析构函数的调用顺序(2) 对于如下的代码: #include<iostream> using namespace std; class CBase { priva ...

  8. C++学习笔记(6)----基类和派生类的构造函数和析构函数的执行顺序

    基类和派生类:构造函数和析构函数的执行顺序 在Visual Studio中,新建控制台工程,构造类如下: #include<iostream> using namespace std; c ...

  9. c++学习笔记4,派生类的构造函数与析构函数的调用顺序(一)

    測试源代码: //測试派生类的构造函数的调用顺序何时调用 //Fedora20 gcc version=4.8.2 #include <iostream> using namespace ...

随机推荐

  1. java 不同数据类型的相互转化

    在工作中经常会遇到需要将数据类型转化的情况,今天抽出时间总结一下. date——string Date date = new Date(); DateFormat dateformat = new S ...

  2. DWZ-JUI+UEditor第二次不显示,UEditor异步加载第二次不显示的解决方案

    使用UEditor-1.4.3中遇到第一次跳转到使用UEditor的界面后,编辑器加载正常,返回后第二次再跳转到这个界面就出现UEditor无法正常加载, 也没百度到答案,看UEditor源码,发现这 ...

  3. iOS界面设计之基础控件的学习 --- UITextField

    学习iOS界面设计也有段时间了,每次写到一些基础控件(如:UILable . UITextField)的时候就深觉应该总结一个函数来实现这些基础控件的属性设置,所以下面就是我对UITextField的 ...

  4. 修改Oracle redo.log文件的大小

    1.查看当前日志组成员: SQL> select member from v$logfile; MEMBER ------------------------------------------ ...

  5. ajax跨域问题(三种解决方案)

    为什么会出现跨域 跨域问题来源于JavaScript的同源策略,即只有 协议+主机名+端口号 (如存在)相同,则允许相互访问.也就是说JavaScript只能访问和操作自己域下的资源,不能访问和操作其 ...

  6. 【Linux学习笔记】Linux C中内联汇编的语法格式及使用方法(Inline Assembly in Linux C)

    http://blog.csdn.net/slvher/article/details/8864996 https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm. ...

  7. libnl3.2.25安装编译

    1,tar zxvf libnl-3.2.25.tar.gz 2,cd libnl-3.2.25 3,./configure --prefix=/usr  --sysconfdir=/etc  --d ...

  8. mybatis 批量插入 返回主键id

    我们都知道Mybatis在插入单条数据的时候有两种方式返回自增主键: 1.对于支持生成自增主键的数据库:增加 useGenerateKeys和keyProperty ,<insert>标签 ...

  9. Mybatis 点点滴滴

    相比 Hibernate ,Mybatis 实在是学习门槛低多了. 1 . 类属性和表字段的自动对应 当向数据库中插入一行数据时,<insert>标签中的占位符#{}中的占位符的值写 mo ...

  10. 【HLSDK系列】Delta 详解

    服务端和客户端总是需要互相交换数据,来做到实时的游戏体验. 很久之前,我们的网速都不是很快,甚至带宽只有 1Mbps (128KB/s)这样的速度,作为当时一个网络实时对战游戏,每时每刻都要传递数据, ...