如何将基类的未知子类放在一个数据结构中并在 C++ 中调用重写的基类函数
Posted
技术标签:
【中文标题】如何将基类的未知子类放在一个数据结构中并在 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++ 中调用重写的基类函数的主要内容,如果未能解决你的问题,请参考以下文章