C++的构造函数问题

***************
*    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
阅读 2.8k
1 个回答

c2 a;

  1. 找到 class c2 的定义,检查其成员, 发现 class c1, 找到其定义。
  2. 找到 c2 的构造函数定义,并找到初始化列表:b(3),a()
  3. 按照成员在 c2 中的定义顺序初始化,即 a -> b。这里要指出代码里一个不好的习惯:构造函数初始化列表顺序尽量与成员定义顺序吻合。c2::c2() :a(), b(3)。所以:

    • 先初始化 a,找到 class c1 的构造函数 c1::c1(),输出 01.
    • 然后初始化 b,找到 class c1 的构造函数 c1::c1(int i),输出 02.
  4. 进入 c2 的构造函数,输出 04

所以输出:01 02 04

c2 b(a);

  1. 指出代码问题:c2(c2 &t);不是一个合格的拷贝构造函数,请复习相关概念。
  2. 参考上一个语句的分析顺序,此处会进入 c2::c2(c2 &t),输出 05
  3. 注意,这里"拷贝构造"函数的初始化列表 a(t.a), b(t.b),实际会进入 class c1 的默认拷贝构造函数,但因为你没有实现并输出东西。所以可能会看成是 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.


最后的建议:

  1. 麻烦不要用什么 c1, c2, a, b 来作为类与对象的名称。习惯非常不好,尽量用有意义的,或者通用的 foo 之类。
  2. 麻烦测试输出的时候,不要用什么 01, 02, 03 这种,一点意义没有不说,还容易把自己看晕。贴出来问别人,还容易把别人搞晕,别人需要花时间理清这些混乱的输出所代表的含义。毫无意义且极其讨厌。完全可以直接输出当前所在的方法名嘛。

参考资料:

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题