父类、构造函数、成员对象的调用时机
2014-06-27 20:57
211 查看
http://hankjin.blog.163.com/blog/static/33731937201010633157934/
在使用new创建对象时,主要完成四项工作:
1 构造父类成员对象
2 构造子类成员对象
3 调用父类构造函数
4 调用子类构造函数
这四项工作的时间顺序是怎样的呢?
原则是:先父类后子类,先成员后函数
一级继承
例如:
class X{
public:
X(){cout<<"X";}
};
class A{
public:
X x1;
A(){cout<<"A";}
};
class B: public A{
public:
X x2;
B(){cout<<"B";}
};
int main(){
B b;
}
构造对象B时,根据第1个原则:先父类后子类,先构造A(1),然后构造B(2)。
构造A(1):
然后根据第2个原则,先成员后函数,先构造A的成员x1,即先调用X构造函数,然后再调用A构造函数
构造B(2):
根据第2个原则,先成员后函数,先构造B的成员x2,即先调用X构造函数,然后再调用B构造函数
因此输出为:
XAXB
多级继承
在一级继承中这个比较容易分析,在多级继承中就会复杂些,但坚持这两个原则,细心分析也不会出问题的。
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
class X{
public:
X(){cout<<"X";}
};
class Y{
public:
Y(){cout<<"Y";}
};
class A{
public:
A(){cout<<"A";}
~A(){cout<<"~A";}
};
class B: public A{
public:
Y x;
A a;
Y y;
B(){cout<<"B";}
~B(){cout<<"~B";}
};
class C: public B{
protected:
X x;
B b;
A a;
X y;
public:
C(){cout<<"C";}
~C(){cout<<"~C";}
};
int main(){
C *c = new C();
delete c;
}
这个程序的输出就比较复杂:
AYAYBXAYAYBAXC~C~A~B~A~A~B~A~A
开始分析:
先父类后子类,所以先构造B(1),然后构造C(2)
构造B(1)的过程如下:
也是先构造A(1.1),然后构造B(1.2)
构造A(1.1)的过程如下:
调用A的构造函数,输出A(第一个输出字符)
构造B(1.2)的过程如下:
先成员(1.2.1)后构造(1.2.2),
成员(1.2.1)的过程如下:
B的成员有Y,A,Y,所以构造Y,A,Y,输出YAY(第二到四个字符)
构造(1.2.2)的过程如下:
B的构造函数,输出B(第五个字符)
所以构造B一共会输出YAYB四个字符
构造C(2)的过程如下:
先成员(2.1)后构造(2.2)
成员(2.1)的过程如下:
C的成员有XBAX
所以构造X,输出X(第六个字符)
构造B输出AYAYB(第七到十一个字符)
构造A输出A(第十二个字符)
构造X输出X(第十三个字符)
构造(2.2)
输出C(第十四个字符)
最后按照完全相反的顺序调用析构函数
在使用new创建对象时,主要完成四项工作:
1 构造父类成员对象
2 构造子类成员对象
3 调用父类构造函数
4 调用子类构造函数
这四项工作的时间顺序是怎样的呢?
原则是:先父类后子类,先成员后函数
一级继承
例如:
class X{
public:
X(){cout<<"X";}
};
class A{
public:
X x1;
A(){cout<<"A";}
};
class B: public A{
public:
X x2;
B(){cout<<"B";}
};
int main(){
B b;
}
构造对象B时,根据第1个原则:先父类后子类,先构造A(1),然后构造B(2)。
构造A(1):
然后根据第2个原则,先成员后函数,先构造A的成员x1,即先调用X构造函数,然后再调用A构造函数
构造B(2):
根据第2个原则,先成员后函数,先构造B的成员x2,即先调用X构造函数,然后再调用B构造函数
因此输出为:
XAXB
多级继承
在一级继承中这个比较容易分析,在多级继承中就会复杂些,但坚持这两个原则,细心分析也不会出问题的。
#include <iostream>
#include <fstream>
#include <cstring>
using namespace std;
class X{
public:
X(){cout<<"X";}
};
class Y{
public:
Y(){cout<<"Y";}
};
class A{
public:
A(){cout<<"A";}
~A(){cout<<"~A";}
};
class B: public A{
public:
Y x;
A a;
Y y;
B(){cout<<"B";}
~B(){cout<<"~B";}
};
class C: public B{
protected:
X x;
B b;
A a;
X y;
public:
C(){cout<<"C";}
~C(){cout<<"~C";}
};
int main(){
C *c = new C();
delete c;
}
这个程序的输出就比较复杂:
AYAYBXAYAYBAXC~C~A~B~A~A~B~A~A
开始分析:
先父类后子类,所以先构造B(1),然后构造C(2)
构造B(1)的过程如下:
也是先构造A(1.1),然后构造B(1.2)
构造A(1.1)的过程如下:
调用A的构造函数,输出A(第一个输出字符)
构造B(1.2)的过程如下:
先成员(1.2.1)后构造(1.2.2),
成员(1.2.1)的过程如下:
B的成员有Y,A,Y,所以构造Y,A,Y,输出YAY(第二到四个字符)
构造(1.2.2)的过程如下:
B的构造函数,输出B(第五个字符)
所以构造B一共会输出YAYB四个字符
构造C(2)的过程如下:
先成员(2.1)后构造(2.2)
成员(2.1)的过程如下:
C的成员有XBAX
所以构造X,输出X(第六个字符)
构造B输出AYAYB(第七到十一个字符)
构造A输出A(第十二个字符)
构造X输出X(第十三个字符)
构造(2.2)
输出C(第十四个字符)
最后按照完全相反的顺序调用析构函数
相关文章推荐
- 父类、构造函数、成员对象的调用时机
- 父类、构造函数、成员对象的调用时机
- C++ 中构造函数对父类及成员对象的初始化时机
- c++结构体中包含类对象成员的问题 malloc函数不能调用构造函数 new可以
- C++构造函数的自动调用(调用一个父类的构造函数,有显性调用最好,否则就默认调用无参数的构造函数)——哲学思想:不调用怎么初始化父类的成员数据和VMT?
- 全局对象构造函数的调用时机
- C++构造函数、拷贝构造函数、赋值运算符重载 调用时机 GCC与VC在对象作为返回值的不同处理
- 为什么在创建子类对象的时候会调用父类的构造函数
- C++ 转换类型运算符 调用构造函数将变量转化成为一个对象的成员变量
- 父类的成员对象、父类、子类的构造函数的执行顺序
- 对象反序列化时,如果父类未实现序列化接口,则反序列出的对象会再次调用父类的构造函数来完成属于父类那部分内容的初始化
- 创建子类对象会调用父类的初始化方法,而不只是构造函数
- 为什么在实例化子类的对象的时候会调用先调用父类的构造函数
- 静态变量、实例变量初始化时机,以及子类隐藏父类成员时,创建子类对象的一些问题
- PHP面向对象学习源码备份(二)——调用父类构造函数
- 子类继承父类,那么子类实例化时对象调用的是父类还是子类的构造函数?
- 不同情形下 对象的构造函数和析构函数的调用并不相同
- 利用C++的operator new实现同一对象多次调用构造函数
- 使用REPLACEMENT NEW来调用对象的构造函数,从而实现任意内存位置的对象实例化....
- const对象调用非const成员函数