C++ 成员类 (类里面包含另一类的对象) 构造函数调用问题

时间:2022-09-30 23:58:00
    各位高手,本菜鸟在阅读他人代码的时候,遇到了一个“成员类”
(类里面包含另一个类的对象) 的构造函数调用问题,具体问题如下:


#include <iostream>
using namespace std;

class A {

public: 

int mInt;

A()
{
    cout << " in A Default Constructor :  mInt = " << mInt << endl;
    mInt = 0;
}

void setIntVal(int mSet)
{
    cout << " in setIntVal : mInt = " << mInt << " mSet = " << mSet << endl;
    if(mInt < mSet)
    {
        mInt = mSet;
    }
}

};

class B {

private: 
    int b;
    A  aObj;
public: 
    B()
    {
     cout << " in B Default Constructor" << endl;
        b = 10;
        aObj.setIntVal(20);
    }

};

int main() {
// your code goes here

    B * pB = new B();
    
    delete pB;
    
    return 0;
}


问题: A中的构造函数会被调用么? 为什么?


程序运行结果:

  in A Default Constructor :  mInt = 0
 in B Default Constructor
 in setIntVal : mInt = 0 mSet = 20



本人属C++菜鸟一枚,以前是搞C的。自己写C++的时候,如果需要调用
A类的构造函数,会通过在B类的构造函数那里去“显示调用”,比如通过
构造函数的初始化列表,或者去new一个A类的对象。但对于这种“隐式”的
处理,小弟就看不懂了。

弱问下: 这个运行结果,与A类定义,实现的无参构造函数也有关吧? 要是
换成有参数的就不行了吧? 这种无参数的构造函数,是这种情况下默认
调用的构造函数吗?

如果方便,还请高手释疑后顺便给个相关知识点的参考链接,小弟再参考参考。

求各位大大指点了,万分感谢!!!  C++ 成员类 (类里面包含另一类的对象) 构造函数调用问题

16 个解决方案

#1


只要有“创建”(非专业的叫法)对象的过程,对象类的构造函数的调用不可避免(除非类的作者没有显式提供
任何
构造函数)
B类构造函数中不写对aObj的构造,相当于其实写了": aObj()"。就算你故意不懈B类的构造函数,就是因为aObj有个自定义的构造函数而会导致编译器暗中给你生成一个B()并且用其调用aObj()

#2


class B有一个member: A aObj;
那构造B对象时,肯定会先构造A对象,就肯定会调用A的构造函数。

#3


楼主,想在C++的路上走远一点,自己认认真真啃下一本合格的教材是最低要求的。
不要想偷懒啊。

#4


1.这个运行结果,与A类定义,实现的无参构造函数也有关吧?
肯定有关,因为B中包含A,所以在构造B时会先构造A

   B()//B的构造函数,虽然没有显示调用A的ctor,但是相当于在初始化列表中有个aObj()
    {
        cout << " in B Default Constructor" << endl;
        b = 10;
        aObj.setIntVal(20);
    }

2.要是换成有参数的就不行了吧?
这要看A中是否提供了默认构造函数,
如果A没有提供默认构造函数,并且用户声明了一个带参数的构造函数,那么编译器不会合成出一个默认的出来,所以在B的初始化列表中需要显示提供构造A所需的参数。
相反,如果A的众多构造函数里有一个默认构造函数,那么B的构造函数中就算没有显示调用A的,编译器也会帮我们调用

#5


A()
{
    cout << " in A Default Constructor :  mInt = " << mInt << endl;
    mInt = 0;
}
这里很纳闷为什么先输出后赋值的情况下mInt还是会等于0?不应该是乱码吗?

#6


 in A Default Constructor :  mInt = 0
这个地方,我想是楼主写错了吧。。。。。 要不然就是太巧合了 C++ 成员类 (类里面包含另一类的对象) 构造函数调用问题

#7


main->需要创建一个B*的变量->找到B类->需要一个int成员->需要一个A类成员->找到A类->需要一个int成员->构造A类->打印->给mInt赋值(赋值在后为什么执行的时候就已经是0了,感到迷惑)->构造A类完成实例化B类中的aObj->执行B类的构造函数->输出->赋值->调用aObj成员的setIntVal(int)方法->构造B完成->在main()中完成了pB的实例化。以前有人跟我说过构造函数就是需要确定一个类在内存中所占用的长度,试问当你创建一个类的时候不知道给他分配多大空间又怎么继续进行呢?  不足之处还请批评指正。

#8


引用 5 楼 axqscz 的回复:
A()
{
    cout << " in A Default Constructor :  mInt = " << mInt << endl;
    mInt = 0;
}
这里很纳闷为什么先输出后赋值的情况下mInt还是会等于0?不应该是乱码吗?


这个我觉得没错啊!因为mInt在静态时候就已经完成了赋值,你在建立new B()时候应该就已经完成赋值了,这是我的理解

#9


请阅读C++ primer  第十一章  十二章,你想知道的,里面都有;我这有电子版,想要的话可以给你

#10


引用 8 楼 u010222864 的回复:
Quote: 引用 5 楼 axqscz 的回复:

A()
{
    cout << " in A Default Constructor :  mInt = " << mInt << endl;
    mInt = 0;
}
这里很纳闷为什么先输出后赋值的情况下mInt还是会等于0?不应该是乱码吗?


这个我觉得没错啊!因为mInt在静态时候就已经完成了赋值,你在建立new B()时候应该就已经完成赋值了,这是我的理解



我vs2010实测结果是:
 in A Default Constructor :  mInt = -842150451
 in B Default Constructor
 in setIntVal : mInt = 0 mSet = 20
Press any key to continue . . .


new B()时候怎么会先去给A的成员赋值? 楼主肯定哪里搞错了吧?

#11


引用 10 楼 shenzhimingdashen 的回复:
Quote: 引用 8 楼 u010222864 的回复:

Quote: 引用 5 楼 axqscz 的回复:

A()
{
    cout << " in A Default Constructor :  mInt = " << mInt << endl;
    mInt = 0;
}
这里很纳闷为什么先输出后赋值的情况下mInt还是会等于0?不应该是乱码吗?


这个我觉得没错啊!因为mInt在静态时候就已经完成了赋值,你在建立new B()时候应该就已经完成赋值了,这是我的理解



我vs2010实测结果是:
 in A Default Constructor :  mInt = -842150451
 in B Default Constructor
 in setIntVal : mInt = 0 mSet = 20
Press any key to continue . . .


new B()时候怎么会先去给A的成员赋值? 楼主肯定哪里搞错了吧?

的确是我理解错了一个地方,我没注意构造函数,是我的错误,不好意思

#12


引用 3 楼 taodm 的回复:
楼主,想在C++的路上走远一点,自己认认真真啃下一本合格的教材是最低要求的。
不要想偷懒啊。


谢谢,有点C++基础,但以前没这么用过,都是自己写的显示调用构造函数的。

C++ 成员类 (类里面包含另一类的对象) 构造函数调用问题

#13


引用 5 楼 axqscz 的回复:
A()
{
    cout << " in A Default Constructor :  mInt = " << mInt << endl;
    mInt = 0;
}
这里很纳闷为什么先输出后赋值的情况下mInt还是会等于0?不应该是乱码吗?


这个。。。本来应该是个随机值的,但我用的编译器就是给出了这样的结果。。。

#14


引用 9 楼 ss_bornli 的回复:
请阅读C++ primer  第十一章  十二章,你想知道的,里面都有;我这有电子版,想要的话可以给你


谢谢,已经在《 12.4.3 默认构造函数》 章节找到答案:

具有类类型的成员通过运行各自的默认构造函数来进行初始化。

#15


引用 13 楼 happy08god 的回复:
Quote: 引用 5 楼 axqscz 的回复:

A()
{
    cout << " in A Default Constructor :  mInt = " << mInt << endl;
    mInt = 0;
}
这里很纳闷为什么先输出后赋值的情况下mInt还是会等于0?不应该是乱码吗?


这个。。。本来应该是个随机值的,但我用的编译器就是给出了这样的结果。。。

看来你的运气是相当的牛B

#16


我发现从我开始问了个很2的问题之后大家都晕了,看来基本功很总要啊!

#1


只要有“创建”(非专业的叫法)对象的过程,对象类的构造函数的调用不可避免(除非类的作者没有显式提供
任何
构造函数)
B类构造函数中不写对aObj的构造,相当于其实写了": aObj()"。就算你故意不懈B类的构造函数,就是因为aObj有个自定义的构造函数而会导致编译器暗中给你生成一个B()并且用其调用aObj()

#2


class B有一个member: A aObj;
那构造B对象时,肯定会先构造A对象,就肯定会调用A的构造函数。

#3


楼主,想在C++的路上走远一点,自己认认真真啃下一本合格的教材是最低要求的。
不要想偷懒啊。

#4


1.这个运行结果,与A类定义,实现的无参构造函数也有关吧?
肯定有关,因为B中包含A,所以在构造B时会先构造A

   B()//B的构造函数,虽然没有显示调用A的ctor,但是相当于在初始化列表中有个aObj()
    {
        cout << " in B Default Constructor" << endl;
        b = 10;
        aObj.setIntVal(20);
    }

2.要是换成有参数的就不行了吧?
这要看A中是否提供了默认构造函数,
如果A没有提供默认构造函数,并且用户声明了一个带参数的构造函数,那么编译器不会合成出一个默认的出来,所以在B的初始化列表中需要显示提供构造A所需的参数。
相反,如果A的众多构造函数里有一个默认构造函数,那么B的构造函数中就算没有显示调用A的,编译器也会帮我们调用

#5


A()
{
    cout << " in A Default Constructor :  mInt = " << mInt << endl;
    mInt = 0;
}
这里很纳闷为什么先输出后赋值的情况下mInt还是会等于0?不应该是乱码吗?

#6


 in A Default Constructor :  mInt = 0
这个地方,我想是楼主写错了吧。。。。。 要不然就是太巧合了 C++ 成员类 (类里面包含另一类的对象) 构造函数调用问题

#7


main->需要创建一个B*的变量->找到B类->需要一个int成员->需要一个A类成员->找到A类->需要一个int成员->构造A类->打印->给mInt赋值(赋值在后为什么执行的时候就已经是0了,感到迷惑)->构造A类完成实例化B类中的aObj->执行B类的构造函数->输出->赋值->调用aObj成员的setIntVal(int)方法->构造B完成->在main()中完成了pB的实例化。以前有人跟我说过构造函数就是需要确定一个类在内存中所占用的长度,试问当你创建一个类的时候不知道给他分配多大空间又怎么继续进行呢?  不足之处还请批评指正。

#8


引用 5 楼 axqscz 的回复:
A()
{
    cout << " in A Default Constructor :  mInt = " << mInt << endl;
    mInt = 0;
}
这里很纳闷为什么先输出后赋值的情况下mInt还是会等于0?不应该是乱码吗?


这个我觉得没错啊!因为mInt在静态时候就已经完成了赋值,你在建立new B()时候应该就已经完成赋值了,这是我的理解

#9


请阅读C++ primer  第十一章  十二章,你想知道的,里面都有;我这有电子版,想要的话可以给你

#10


引用 8 楼 u010222864 的回复:
Quote: 引用 5 楼 axqscz 的回复:

A()
{
    cout << " in A Default Constructor :  mInt = " << mInt << endl;
    mInt = 0;
}
这里很纳闷为什么先输出后赋值的情况下mInt还是会等于0?不应该是乱码吗?


这个我觉得没错啊!因为mInt在静态时候就已经完成了赋值,你在建立new B()时候应该就已经完成赋值了,这是我的理解



我vs2010实测结果是:
 in A Default Constructor :  mInt = -842150451
 in B Default Constructor
 in setIntVal : mInt = 0 mSet = 20
Press any key to continue . . .


new B()时候怎么会先去给A的成员赋值? 楼主肯定哪里搞错了吧?

#11


引用 10 楼 shenzhimingdashen 的回复:
Quote: 引用 8 楼 u010222864 的回复:

Quote: 引用 5 楼 axqscz 的回复:

A()
{
    cout << " in A Default Constructor :  mInt = " << mInt << endl;
    mInt = 0;
}
这里很纳闷为什么先输出后赋值的情况下mInt还是会等于0?不应该是乱码吗?


这个我觉得没错啊!因为mInt在静态时候就已经完成了赋值,你在建立new B()时候应该就已经完成赋值了,这是我的理解



我vs2010实测结果是:
 in A Default Constructor :  mInt = -842150451
 in B Default Constructor
 in setIntVal : mInt = 0 mSet = 20
Press any key to continue . . .


new B()时候怎么会先去给A的成员赋值? 楼主肯定哪里搞错了吧?

的确是我理解错了一个地方,我没注意构造函数,是我的错误,不好意思

#12


引用 3 楼 taodm 的回复:
楼主,想在C++的路上走远一点,自己认认真真啃下一本合格的教材是最低要求的。
不要想偷懒啊。


谢谢,有点C++基础,但以前没这么用过,都是自己写的显示调用构造函数的。

C++ 成员类 (类里面包含另一类的对象) 构造函数调用问题

#13


引用 5 楼 axqscz 的回复:
A()
{
    cout << " in A Default Constructor :  mInt = " << mInt << endl;
    mInt = 0;
}
这里很纳闷为什么先输出后赋值的情况下mInt还是会等于0?不应该是乱码吗?


这个。。。本来应该是个随机值的,但我用的编译器就是给出了这样的结果。。。

#14


引用 9 楼 ss_bornli 的回复:
请阅读C++ primer  第十一章  十二章,你想知道的,里面都有;我这有电子版,想要的话可以给你


谢谢,已经在《 12.4.3 默认构造函数》 章节找到答案:

具有类类型的成员通过运行各自的默认构造函数来进行初始化。

#15


引用 13 楼 happy08god 的回复:
Quote: 引用 5 楼 axqscz 的回复:

A()
{
    cout << " in A Default Constructor :  mInt = " << mInt << endl;
    mInt = 0;
}
这里很纳闷为什么先输出后赋值的情况下mInt还是会等于0?不应该是乱码吗?


这个。。。本来应该是个随机值的,但我用的编译器就是给出了这样的结果。。。

看来你的运气是相当的牛B

#16


我发现从我开始问了个很2的问题之后大家都晕了,看来基本功很总要啊!