C++派生类构造函数和析构函数调用顺序

++派生类构造函数调用顺序(详解)

我们来看下面一段代码:
  class B1
  {
  public:
  B1(int i) {cout<<"constructing B1 "<<i<<endl;}
  };
  class B2
  {
  public:
  B2(int j) {cout<<"constructing B2 "<<j<<endl;}
  };
  class B3
  {
  public:
  B3(){cout<<"constructing B3 *"<<endl;}
  };
  class C: public B2, public B1, public B3
  {
  public:
  C(int a, int b, int c, int d):B1(a),memberB2(d),memberB1(c),B2(b){}
  private:
  B1 memberB1;
  B2 memberB2;
  B3 memberB3;
  };
  void main( )
  { C obj(1,2,3,4); }
  运行后的结果如下:
  constructing B2 2
  constructing B1 1
  constructing B3 *
  constructing B1 3
  constructing B2 4
  constructing B3 *
  为什么会有以上的结果?
  众所周知构造函数的执行次序如下:
  调用基类构造函数,调用顺序按照他们的继承时声明的顺序。
  调用内嵌成员对象的构造函数,调用顺序按照他们在类中声明的顺序。
  派生类的构造函数体中的内容。
  析构函数的调用顺序相反。
  那么再来看以上的例子就很容易理解了。B2、B1、B3是C的基类,按照上述的顺序,我们先要构造基类,然后才是子对象,最后是其本身的构造函数所以先要执行这三个类的构造函数。在构造时按照他们在类中的顺序,首先调用B2的构造函数
  B2(int j) {cout<<"constructing B2 "<<j<<endl;}
  由于在默认参数列表
  C(int a, int b, int c, int d):B1(a),memberB2(d),memberB1(c),B2(b){}
  中,将b的值传给了B2的构造函数,b为2,故打印出:
  constructing B2 2
  接下来要构造的是B1了。显然在C的默认参数构造列表中将a的值传给了B1,
  所以打印出:
  constructing B1 1
  B3在构造时没有传递参数,调用B3(){cout<<"constructing B3 *"<<endl;}
  打印出:
  cout<<"constructing B3 *
  这时基类的构造函数已经执行完毕,接着该处理内嵌成员对象的构造函数了。
  我们看到C类有三个对象:B1 memberB1;B2 memberB2;B3 memberB3;,按照构造函数的调用顺序,我们需要按照他们在类中声明的顺序来分别构造memberB1、memberB2、 memberB3。在默认的参数列表中,用c来构造了memberB1,用d来构造memberB2,
  故打印出:
  constructing B1 3
  constructing B2 4
  constructing B3 *
  最后调用本身的构造函数,由于函数体为空,故什么也没有打印出来。
  总结下来,我们必须明确的是当一个类继承与基类,并且自身还包含有其他类的成员对象的时候,构造函数的调用顺序为:调用基类的构造函数->调用成员对象的构造函数->调用自身的构造函数构造函数的调用次序完全不受构造函数初始化列表的表达式中的次序影响,与基类的声明次数和成员对象在函数中的声明次序有关
再如:
#include<iostream.h>
class A
{
protected:
     char c;
public:
     A(char ch)
     {
           c=ch;
            cout<<"c="<<c<<endl;
            cout<<"类A构造函数被调用"<<endl;
     }
     ~A()
     {
            cout<<"类A析构函数被调用"<<endl;
     }
};
class B
{
protected:
     int i;
public:
     B(int j)
     {
            i=j;
            cout<<"i="<<i<<endl;
           cout<<"类B构造函数被调用"<<endl;
     }
     ~B()
     {
           cout<<"类B析构函数被调用"<<endl;
     }
};
class C:public A,B
{
private:
     int k;
public:
     C(char ch,int ii,int kk):A(ch),B(ii),k(kk)
     {
           cout<<"k="<<k<<endl;
           cout<<"类C构造函数被调用"<<endl;
     }
     ~C()
     {
           cout<<"类C析构函数被调用"<<endl;
     }
};
void main()
{
     C A('B',10,15);
}
输出结果:
c=B
类A构造函数被调用
i=10
类B构造函数被调用
k=15
类C构造函数被调用
类C析构函数被调用
类B析构函数被调用
类A析构函数被调用

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值