使用多态集合

Using polymorphic collection

本文关键字:集合 多态      更新时间:2023-10-16

我遇到如下情况:

#include <set>
#include <map>
#include <vector>
#include <string>
class BaseCollection {
// I don't know what to keep here
// I want to have access to collection elements
// seems I need to implmement begin(), end() for collections
};
class CollectionA : public BaseCollection {
public: // in real code this will be private
std::vector<double> coll_;
};
class CollectionB : public BaseCollection {
public: // in real code this will be private
std::set<double> coll_;
};
class CollectionC : public BaseCollection {
public: // in real code this will be private
std::map<std::string, double> coll_;
};
class Base {
public:
virtual BaseCollection* getColl() = 0;
};
class A : public Base {
virtual BaseCollection* getColl() { return &coll_; }
public: // in real code this will be private
CollectionA coll_;
};
class B : public Base {
virtual BaseCollection* getColl() { return &coll_; }
public: // in real code this will be private
CollectionB coll_;
};
class C : public Base {
virtual BaseCollection* getColl() { return &coll_; }
public: // in real code this will be private
CollectionC coll_;
};
class Container {
public:
typedef std::map<std::string, Base*>::const_iterator const_iterator;
Container::const_iterator begin() const { return objects_.begin(); }
public: // in real code this will be private
std::map<std::string, Base*> objects_;
};

int main() {
// somewhere we're creating objects of different types and filling their collections
A objA;
// suppose we filled objA.coll_ somehow
Base* ptrA = new A;
ptrA = &objA;
// somwhere we're iterationg over Container
Container c;
c.objects_["objA"] = ptrA;
Container::const_iterator itBeg = c.begin();
BaseCollection* coll = itBeg->second->getColl();
// and here I want to itarate over collection
}

因此,我需要以某种方式为BaseCollection定义至少begin()end(),并在派生类中实现它们
或者我可能需要使用模板?但我想不通
我该怎么做
或者可能不可能,我需要为每种类型(ABC)保留单独的容器

EDIT:所以,我有一个Base类,以及从它派生的一些类(ABC),它们包含不同类型的集合。实际上,我想要的是Base中的一个接口,用于迭代它当前指向的派生类的集合

提前谢谢。

如果您希望能够以基类型或类型a、b或c访问元素的,那么多态性是最好的选择。但是你不应该继承这个系列。所以你的基本类型应该是这样的:

class baseType{
//define share parameters here like:
int baseInt;
//and pure virtual functions like:
int elementType() = 0;
}

你的收藏会是这样的:

class BaseCollection {
std::list<baseType> baseList;
};

继承类型如下所示:

class typeA:baseType{
//a pure virtual has to be overridden so:
int elementType() { return 1;}
}

请注意,集合将始终返回baseType类型的元素。如果你想知道继承类型是什么,有两种方法。

  • 对baseType的指针执行静态强制转换,强制转换为所需的类型。如果类型不是所需的类型,则返回null
  • 创建一个(纯)虚拟函数,该函数返回一个整数或其他类型的变量,指示类型。就像上面所做的

当继承类型过多时,您可能需要执行后者。因为会有很多静态广播

EDIT:您可以实现迭代器的并行层次结构BaseCollection的Base迭代器类和每个派生集合类的一个迭代器。同样,当迭代器之间的值类型不同时,可以将通用值类型定义为某种变体,或者将所有内容都作为字符串返回。

这不是小事。您必须在每个特定的类begin/end和每个派生迭代器中实现值访问函数、复制/比较等运算符。

制作你的值(而不是集合)的基类并将指向对象的指针存储在标准容器中,这不是更容易吗?

原始使用模板进行代码重用

使用多态性提供相同的接口并隐藏实现

在您的案例中,您使用了在派生类中具有不同类型的不同容器。这只是一个例子,还是应该是这样?如果是第二种,模板在这里就没有帮助了。

实现开始/结束不是问题,例如virtual void begin() =0;派生类中的实现应该设置一些指向特定容器中位置的私有索引或迭代器。

问题还在于,您将返回哪种类型?一种变体可能是一种解决方案。