***************
* class.h *
***************
#include<iostream>
using namespace std;
class c1
{
public:
c1();
c1(int i);
~c1();
private:
int d;
};
c1::c1()
{
cout<<"01"<<endl;
}
c1::c1(int i)
{
cout<<"02"<<endl;
d=i;
}
c1::~c1()
{
cout<<"03"<<endl;
}
class c2
{
public:
c2();
c2(c2 &t);
~c2();
private:
c1 a;
c1 b;
};
c2::c2():b(3),a()
{
cout<<"04"<<endl;
}
c2::c2(c2 &t):b(t.b),a(t.a)
{
cout<<"05"<<endl;
}
c2::~c2()
{
cout<<"06"<<endl;
}
************
* main.cpp *
*************
#include<iostream>
#include "class.h"
using namespace std;
int main()
{
c2 a;
c2 b(a);
return 0;
}
<pre><code>今天才看完构造函数与析构函数
练习就蒙了
求指教! 谢谢。。
答案是
</code></pre>
01
02
04
05
06
03
03
06
03
03
c2
的定义,检查其成员, 发现 classc1
, 找到其定义。c2
的构造函数定义,并找到初始化列表:b(3),a()
。c2
中的定义顺序初始化,即 a -> b。这里要指出代码里一个不好的习惯:构造函数初始化列表顺序尽量与成员定义顺序吻合。即c2::c2() :a(), b(3)
。所以:a
,找到 classc1
的构造函数c1::c1()
,输出01
.b
,找到 classc1
的构造函数c1::c1(int i)
,输出02
.c2
的构造函数,输出04
。所以输出:
01 02 04
c2(c2 &t);
不是一个合格的拷贝构造函数,请复习相关概念。c2::c2(c2 &t)
,输出05
a(t.a), b(t.b)
,实际会进入 classc1
的默认拷贝构造函数,但因为你没有实现并输出东西。所以可能会看成是a
,b
两个成员没有初始化一样。所以输出:
05
当 main 函数终结退出之际,对象
a
,b
发生析构,析构顺序与构造顺序相反。即先析构b
,进入c2::~c2()
,输出06
;辗转析构对象b
的成员,即先b.b
,然后b.a
,两者都要进入c1::~c1()
, 故输出两次03
。再析构对象a
,同理,会输出06 03 03
。故,输出
06 03 03 06 03 03
.最后的建议:
c1
,c2
,a
,b
来作为类与对象的名称。习惯非常不好,尽量用有意义的,或者通用的foo
之类。01
,02
,03
这种,一点意义没有不说,还容易把自己看晕。贴出来问别人,还容易把别人搞晕,别人需要花时间理清这些混乱的输出所代表的含义。毫无意义且极其讨厌。完全可以直接输出当前所在的方法名嘛。参考资料: