C++中,建立子类对象的时候,会调用基类的构造函数,

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++中,建立子类对象的时候,会调用基类的构造函数,相关的知识,希望对你有一定的参考价值。

那么我就想问:到底在内存中有没有,为父类对象分配内存?还是说只是有子类的对象?

参考技术A 派生类的对象中包含了基类的对象。例外是存在“空基类优化”(empty base optimization)的场合,此时基类对象不占内存,不过只有基类对象没有数据成员(“为空”)的时候才有空基类优化,所以这没有什么影响。 参考技术B

会调用基类的构造函数,内存中的对象应该看作一层包一层的形象,推荐一本书和这个问题相关的深度探索C++对象模型例子如下,在最后return处打断点

#include <iostream>
 
using namespace std;
class A

public:
    A() cout<<"A()"<<endl;
    ~A()cout<<"~A()"<<endl;
;
class B:public A

    public:
    B() cout<<"B()"<<endl;
    ~B()cout<<"~B()"<<endl;
;

int main()

    A a;
    B b;//构造和析构,B和A都涉及到了
    return 0;//这一行打断点,debug

参考技术C 为父类对象分配了内存,其有两个对象

如何将基类的未知子类放在一个数据结构中并在 C++ 中调用重写的基类函数

【中文标题】如何将基类的未知子类放在一个数据结构中并在 C++ 中调用重写的基类函数【英文标题】:How to put unknown child classes of a base class in one data structure and call an overridden base class function in C++ 【发布时间】:2020-12-31 01:04:12 【问题描述】:

我有一个“链”类,意思是管理具有公共基类的一系列对象的类。 这个链类应该为我添加的任何子类(baseClass)执行成员函数processSample(a, b)

我希望以后能够编写更多子类(使用processSample(a, b) 函数),并将它们添加到链中,而无需编辑链类。 我可以在add 函数中使用模板,但这并不能解决不同数据类型(不同大小)没有数据结构的问题,对吧?

Chain 类中调用的子类的函数都应该被基类中的虚函数覆盖。

class baseClass

public:

    virtual float processSample(int a, float b)
    

    
;


class Chain

    const int maxChilds = 20;
    ?sometype? allChilds[maxChilds];

public:
    float processSample(int c, float d)
    
        for (int i = 0; i < maxChilds; i++)
        
            input = allChilds[i].processSample(a, b);
        

        return input;
    

    void addChild(?sometype? newChild)
    
       allChilds.push_back(newChild)
    

【问题讨论】:

?sometype? -> baseClass * 最有可能,但您可能需要baseClasss 的簿记计数器,由allChilds 指向。如果不添加 maxChilds 实例,迭代到 maxChilds 将是致命的。 std::vector&lt;baseClass*&gt;std::vector&lt;std::reference_wrapper&lt;baseClass&gt;&gt; @ChrisD 拥有此权利。 C++ 中的原始数组没有 push_back 方法。或者任何方法。数组真的很简单也很笨。 这能回答你的问题吗? Store derived class objects in base class variables 【参考方案1】:

您可能希望使用指针或引用,以避免初始化或复制操作作为创建类的一部分。

例如

class Chain

    const int maxChilds = 20;
    baseClass allChilds[maxChilds];

将创建并初始化一个包含 20 个基类实例的数组。而这个:

class Chain

    const int maxChilds = 20;
    baseClass* allChilds[maxChilds];

将创建一个指向 baseClass 的指针数组,它也可以指向任何子类的实例。请考虑哪个类将负责为这些实例分配和取消分配内存(这可以在此类中,也可以在此类的调用者/用户中 - 哪个是理想的将取决于您的设计的其余部分) .你也可以考虑使用智能指针,让它为你管理内存:https://en.cppreference.com/book/intro/smart_pointers

同样:

void addChild(baseClass newChild)

将使用传值传递newChild的副本(使用baseClass的复制构造函数),任何子类的实例都将失败或转换为baseClass的实例。而如果你改为选择:

void addChild(baseClass& newChild)

它将改为使用传递引用,并且该函数将接收对原始对象的引用。

【讨论】:

请注意,要使addChild 真正起作用,您必须绝对确定添加的节点的生命周期匹配或超过Chain 的生命周期。通常你需要a clone method 来创建一个寿命更长的实例,而Chain 拥有它的所有权。 是的 - 代码中还有很多其他错误需要修复:)。我想我会坚持只解决所问的问题,特别是因为复制构造函数/按值传递行为对于来自 Java 之类的东西都是按引用传递的人来说是一个重要的区别。跨度> 【参考方案2】:

virtual 的好处是“调用基类的函数”,而派生类的函数会被执行。

所以?sometype? allChilds[maxChilds];baseClass allChilds[maxChilds];。链应该是对象的持有者,所以addChild(...) 不应该接受子类的实例。它应该创建实例并使用(如有必要)std::move 将其添加到数组中。

备注:使用会更方便

std::vector<baseClass>allChilds;
allChilds.reserve(maxChilds); //reserves the memory but you can still use push back

【讨论】:

以上是关于C++中,建立子类对象的时候,会调用基类的构造函数,的主要内容,如果未能解决你的问题,请参考以下文章

C++中,继承时,创建子类对象,能否在子类构造函数初始化列表里调用基类构造函数?

C++中如何在子类的构造函数中调用基类的构造函数来初始化基类成员变量

关于C++基类与派生类

生成一个派生类对象时,调用基类和派生类构造函数按啥次序

定义子类对象时要先调用基类构造函数,是应该哪样理解呢

继承与多态