#include <iostream>
#include <cstdio>
#include <cmath>
#include <climits>
#include <iomanip>
#include <windows.h>//
#include <iostream>
#define MAX(x,y) (x)>(y)?(x):(y)
#include <string.h>
using namespace std;
class A
{
public:
A()
{
a=0;
cout<<"A() Default constructor called."<<a<<endl;
}
A(int i)
{
a=i;
cout<<"A(int )Constructor called."<<a<<endl;
}
~A()
{ cout<<"A Destructor called."<<a<<endl; }
void Print()
{ cout<<a<<','; }
int Geta()
{ return a; }
private:
int a;
};
class B:public A
{
public:
B()
{
b=0;
cout<<"B() Default constructor called."<<b<<endl;
}
B(int i,int j,int k):A(i),aa(j)
{
b=k;
cout<<"B(int,int,int) Constructor called."<<b<<endl;
}
~B()
{ cout<<"B Destructor called."<<b<<endl; }
void Print()
{
A::Print();
cout<<b<<','<<aa.Geta()<<endl;
}
private:
int b;
A aa;
};
int main()
{
B bb[2];
bb[0]=B(7,8,9);
bb[1]=B(12,13,14);
for(int i=0;i<2;i++)
bb[i].Print();
}
结果是
A() Default constructor called.0
A() Default constructor called.0
B() Default constructor called.0
A() Default constructor called.0
A() Default constructor called.0
B() Default constructor called.0
A(int )Constructor called.7
A(int )Constructor called.8
B(int,int,int) Constructor called.9
B Destructor called.9
A Destructor called.8
A Destructor called.7
A(int )Constructor called.12
A(int )Constructor called.13
B(int,int,int) Constructor called.14
B Destructor called.14
A Destructor called.13
A Destructor called.12
7,9,8
12,14,13
B Destructor called.14
A Destructor called.13
A Destructor called.12
B Destructor called.9
A Destructor called.8
A Destructor called.7
首先是补习下基础知识。
1派生类构造函数的执行顺序如下:
优先级一:先执行基类构造函数
优先级二:再执行子对象的构造函数(如果有子对象的话)
优先级三:最后执行派生类构造函数的函数体
派生类析构函数的执行顺序如下:
优先级一:先执行派生类析构函数的函数体
优先级二:再执行子对象所在类的析构函数(如果有子对象的话)
优先级三:最后执行直接基类中的析构函数
为了方便大家明白我在输出语句中添加了部分修饰为了方便大家看懂
我们进行一步一步的解析,对源代码进行解析操作。我们可以先分析部分代码,从main函数里面开始,我们先看B bb[2]这是数组中有两个对象,下面的代码先注释掉,
int main()
{
B bb[2];
// bb[0]=B(7,8,9);
// bb[1]=B(12,13,14);
// for(int i=0;i<2;i++)
// bb[i].Print();
}
其他不变。输出结果
A() Default constructor called.0
A() Default constructor called.0
B() Default constructor called.0
A() Default constructor called.0
A() Default constructor called.0
B() Default constructor called.0
B Destructor called.0
A Destructor called.0
A Destructor called.0
B Destructor called.0
A Destructor called.0
A Destructor called.0
改动一:
这里大家很困惑的是为什么会有两个A() Default constructor called.0,之后是B() Default constructor called.0而不是一个A() Default constructor called.0,之后是B() Defaultconstructor called.0,派生类B中有两个构造函数,在带参的构造函数显示的包含了直接基类的构造函数,而在默认的构造函数中却隐含了直接基类的构造函数, B(int i,int j,int k):A(i),aa(j)的我们在派生类B声明了A aa这个对象,所以带参的构造函数中显式的包含了基类的构造函数,也就是为什末输出两个A() Default constructor called.0之后是B() Default constructor called.0,
int main()
{
B bb[2];
bb[0]=B(7,8,9);
bb[1]=B(12,13,14);
// for(int i=0;i<2;i++)
// bb[i].Print();
}
结果是
A() Default constructor called.0
A() Default constructor called.0
B() Default constructor called.0
A() Default constructor called.0
A() Default constructor called.0
B() Default constructor called.0
A(int )Constructor called.7
A(int )Constructor called.8
B(int,int,int) Constructor called.9
B Destructor called.9
A Destructor called.8
A Destructor called.7
A(int )Constructor called.12
A(int )Constructor called.13
B(int,int,int) Constructor called.14
B Destructor called.14
A Destructor called.13
A Destructor called.12
B Destructor called.14
A Destructor called.13
A Destructor called.12
B Destructor called.9
A Destructor called.8
A Destructor called.7
改动二:
将for循环注释掉,输出结果如上,为什末是末尾是7,8,9,因为我们bb[0]=B(7,8,9)7在前面
A(int )Constructor called.7
A(int )Constructor called.8
B(int,int,int) Constructor called.9
之后再进行析构掉,也就是输出了
B Destructor called.9
A Destructor called.8
A Destructor called.7
另一个bb[1]同样的道理
输出结果:7,8,9 因为是代码是这个 位置变化了
B(int i,int j,int k):A(i),aa(j)
{
b=k;
cout<<"B(int,int,int) Constructor called."<<b<<endl;
}
void Print()
{
A::Print();
cout<<b<<','<<aa.Geta()<<endl;
}
最后的一步是都进行析构,派生类的析构函数的执行顺序正好与派生类的构造函数的执行顺序相反。