抱歉,如果我在这里遗漏了一个相当基本的概念,但我正在尝试解决如何维护多个类类型的集合(所有类都派生自同一个父类),并且在检索它们时仍然可以访问它们的子类特定方法从收藏。
作为上下文,我有一个基类(“BaseClass”)和许多类(比如“SubClassA”到“SubClassZ”),它们都派生自这个基类。我还需要维护一个包含所有子类对象的中央索引集合,这些对象是我创建的
typedef unordered_map<std::string, BaseClass*> ItemCollectionType;
ItemCollectionType Items;
该列表将只包含子类对象,但我已将列表成员类型定义为“BaseClass”指针,以便它可以存储任何子类的实例。到目前为止,我假设这种方法没有什么特别糟糕的(但如果我错了,请纠正我)。
我遇到的问题是,有时我需要创建这些集合及其内容的副本。我为此拥有的(简化)代码如下:
ItemCollectionType CopiedItems;
ItemCollectionType::const_iterator it_end = Items.end();
for (ItemCollectionType::const_iterator it = Items.begin(); it != it_end; ++it)
{
BaseClass *src = it->second;
BaseClass *item = new BaseClass(src);
NewItems[item->code] = item;
}
这里明显的问题是编译器只会调用 BaseClass 复制构造函数,而不是“src”实际指向的 SubClass,因为它不知道它是什么类型的 SubClass。
对于这种情况,推荐的方法是什么?我是否应该通过添加到 BaseClass 类型的集合来“丢失”这个子类类型信息?我看不到任何其他方式来维护收藏,但请让我知道任何更好的选择。
每个 SubClass 对象都包含一个数字 ID,表示它是哪种风格的子类;因此,是否可以编写一个函数将该数字 ID 转换为“类型”对象,然后在调用复制构造函数之前使用该对象转换源对象?这是模板的有效用途吗?
当然,这可能是糟糕的编程实践和/或不可能。我只是确定应该有比最简单和最难维护的解决方案更好的选择
switch (src->code)
{
case SubClassTypes::VarietyA:
SubClassA *item = new SubClassA( *((SubClassA*)src) );
Items[item->code] = item;
break;
case SubClassTypes::VarietyB:
SubClassB *item = new SubClassB( *((SubClassB*)src) );
Items[item->code] = item;
break;
...
...
}