类的各类函数的调用顺序
2015-07-30 19:55
274 查看
类的构造函数-》类的成员对象的构造函数-》派生类的构造函数
我们来看下面一段代码:
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<<"constructingB3 *"<<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, intd):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<<"constructingB3 *"<<endl;}
打印出:
cout<<"constructing B3*
这时基类的构造函数已经执行完毕,接着该处理内嵌成员对象的构造函数了。
我们看到C类有三个对象:B1memberB1;B2 memberB2;B3 memberB3;,按照构造函数的调用顺序,我们需要按照他们在类中声明的顺序来分别构造memberB1、memberB2、memberB3。在默认的参数列表中,用c来构造了memberB1,用d来构造memberB2,
故打印出:
constructing B1 3
constructing B2 4
constructing B3 *
最后调用本身的构造函数,由于函数体为空,故什么也没有打印出来。
总结下来,我们必须明确的是当一个类继承与基类,并且自身还包含有其他类的成员对象的时候,构造函数的调用顺序为:调用基类的构造函数->调用成员对象的构造函数->调用自身的构造函数。构造函数的调用次序完全不受构造函数初始化列表的表达式中的次序影响,与基类的声明次数和成员对象在函数中的声明次序有关。
我们来看下面一段代码:
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<<"constructingB3 *"<<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, intd):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<<"constructingB3 *"<<endl;}
打印出:
cout<<"constructing B3*
这时基类的构造函数已经执行完毕,接着该处理内嵌成员对象的构造函数了。
我们看到C类有三个对象:B1memberB1;B2 memberB2;B3 memberB3;,按照构造函数的调用顺序,我们需要按照他们在类中声明的顺序来分别构造memberB1、memberB2、memberB3。在默认的参数列表中,用c来构造了memberB1,用d来构造memberB2,
故打印出:
constructing B1 3
constructing B2 4
constructing B3 *
最后调用本身的构造函数,由于函数体为空,故什么也没有打印出来。
总结下来,我们必须明确的是当一个类继承与基类,并且自身还包含有其他类的成员对象的时候,构造函数的调用顺序为:调用基类的构造函数->调用成员对象的构造函数->调用自身的构造函数。构造函数的调用次序完全不受构造函数初始化列表的表达式中的次序影响,与基类的声明次数和成员对象在函数中的声明次序有关。
相关文章推荐
- JAVA中sleep,wait,yield,join函数解析_ftc
- MRP Force Reservation的作用
- Server Tomcat v7.0 Server at localhost was unable to start within 45 seconds
- 杭电1287(接异或篇)
- 【CSAPP】malloc Lab
- hdu 5326 Work(并查集)
- HDU 5328_Problem Killer
- hdoj 2141 Can you find it? 【二分法】
- jQuery EasyUI 给datagrid绑定右键菜单
- 栈的操作
- 证同测试
- STM32F4XX devices vector table for EWARM toolchain.
- [hdu4292]最大流,拆点
- 使用虚拟机VM运行Linux版OpenERP
- hdu-1551 Cable master
- 花生壳(内网版)做远程桌面登陆
- C语言itoa()函数和atoi()函数详解
- 通过JDBC/ODBC方法连接SQL Servers与MyEclipe(SQL)
- Java读取文件夹大小的6种方法及代码
- 返回局部变量的问题