C ++维护一个混合集合的子类对象 [英] C++ maintaining a mixed collection of subclass objects

查看:135
本文介绍了C ++维护一个混合集合的子类对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我在这里缺少一个相当基本的概念道歉,但我试图解决如何维护多个类类型的集合(所有派生自同一个父类),并仍然可以访问他们的子类特定的方法

Apologies if I'm missing a fairly fundamental concept here, but I'm trying to work out how to maintain a collection of multiple class types (all derived from the same parent) and still have access to their subclass-specific methods when retrieving them from the collection.

作为上下文,我有一个基类(BaseClass)和多个类(例如SubClassA到SubClassZ)所有都派生自这个基类。我还需要维护一个中央索引集合的所有SubClass对象,我创建为

As context, I have one base class ("BaseClass") and a number of classes (say "SubClassA" through "SubClassZ") that all derive from this base class. I also need to maintain a central indexed collection of all SubClass objects, which I have created as

typedef unordered_map<std::string, BaseClass*> ItemCollectionType;
ItemCollectionType Items;

列表将只包含SubClass对象,但我已将列表成员类型定义为BaseClass 指针,以便它可以存储任何子类的实例。到目前为止,我假设这种方法没有什么特别的坏处(但如果我错了,请纠正我)。

The list will only ever contain SubClass objects but I've defined the list member type as a "BaseClass" pointer so that it can store instances of any sub class. So far, I'm assuming there's nothing particularly bad about this approach (but please correct me if I'm wrong).

我遇到的问题是,有时候我需要以创建这些集合及其内容的副本。我有这样的(简化)代码如下:

The issue I have is that sometimes I need to create a copy of these collections and their contents. The (simplified) code I have for this is as follows:

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实际指向的子类的子类,因为它不知道它是什么类型的子类。

The obvious issue here is that the compiler will only call the BaseClass copy constructor, rather than that of the SubClass that "src" actually points to, because it does not know what type of SubClass it is.

对于一种情况这个?我应该甚至在一个情况下,我通过添加到一个类型BaseClass的集合丢失这个子类类型信息?我不能看到任何其他方式来维护收集,但请让我知道任何更好的选择。

What is the recommended approach for a situation like this? Should I even be in a situation where I "lose" this sub class type information by adding to a collection of type BaseClass? I can't see any other way to maintain the collection but please let me know of any better alternative.

每个子类对象包含一个数字ID,指示哪种风味子类作为结果,是否可以编写一个函数,将这个数字ID转换为一个类型对象,然后可以用来转换源对象,然后调用复制构造函数?这是模板化的有效用途吗?

Each SubClass object does contain a numeric ID that indicates which flavour of sub class it is; as a result, is it possible to write a function that translates this numeric ID into a "type" object, which can then be used to cast the source object before calling the copy constructor? Is this a valid use for templating?

当然,这可能是可怕的编程习惯和/或不可能。我只是确定应该有一个比最简单和最小可维护的解决方案更好的选择

Of course, this could be terrible programming practice and/or not possible. I'm just certain there should be a better option than the simplest and least-maintainable solution of

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;
    ...
    ...
}


推荐答案

您可以定义将在每个子类中实现的抽象 Clone 方法。

You can define abstract Clone method which will be implemented in each subclass.

virtual BaseClass* Clone() = 0;

比调用:

for (ItemCollectionType::const_iterator it = Items.begin(); it != it_end; ++it) 
{
    BaseClass *src = it->second;
    NewItems[item->code] = src->Clone();
}

另请注意,C ++支持返回值协方差,因此您的派生类可以返回类型而不仅仅是基类,例如

Also note that C++ support return value covariance so your derived classes can return the exact type and not just the base class, e.g.

// in DerivedClass (which derives from BaseClass)
DerivedClass* Clone() { ... } 

这被认为是一个适当的覆盖,尽管返回类型不是

This is considered a proper override, although the return type is not the same as in the base class.

基于属性将基类指针转换为派生类不被认为是良好的OOP实践。

Casting the base class pointers to derived classes, based on an attribute, is not considered good OOP practice.

这篇关于C ++维护一个混合集合的子类对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆