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 *
最有可能,但您可能需要baseClass
s 的簿记计数器,由allChilds
指向。如果不添加 maxChilds
实例,迭代到 maxChilds
将是致命的。
或std::vector<baseClass*>
或std::vector<std::reference_wrapper<baseClass>>
。
@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++中,继承时,创建子类对象,能否在子类构造函数初始化列表里调用基类构造函数?