【问题标题】:Using polymorphic collection使用多态集合
【发布时间】:2015-04-29 07:24:23
【问题描述】:

我的情况如下:

    #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() 并在派生类中实现它们。
或者也许我需要使用模板?但我想不通。
我该怎么做?
或者这不可能,我需要为每种类型保留单独的容器(A、B、C)。

编辑: 所以,我拥有的是一个Base 类,以及一些从它派生的类(A、B、C),它们包含不同类型的集合。实际上我想要的是Base 中的一个接口来迭代它当前指向的派生类的集合。

提前致谢。

【问题讨论】:

  • 您能否详细说明您的目标是什么?你想要的是一个元素的集合,其中所有元素都是 A 型、B 型或 C 型?您希望能够单独访问它们作为类型 A 还是仅作为基本类型?
  • @laurisvr,是的,集合中的元素是 A 型、B 型或 C 型,我希望能够将它们作为基本类型访问。
  • 你有为集合使用多个子类吗?你不能简单地使用一个模板化的Collection 类并在你的A、B 和C 类中使用它吗?而且我真的不明白A、B 和C 具有共同祖先类的原因,您能否尝试解释一下您的用例?您实际上要解决什么问题? (您可能想了解the XY problem。)
  • @JoachimPileborg,如果我有一个模板化的 Collection 类,那么我的 Base 类也将被模板化,但我希望它不是模板。我将编辑我的问题并编写实际问题。
  • 我已经回答了一个与您的here 非常相似的问题。

标签: c++ templates inheritance


【解决方案1】:

如果您希望能够以基本类型或类型 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。
  • 创建一个(纯)虚函数,它返回一个整数或其他类型的变量,指示类型。就像上面那样。

当继承类型过多时,您可能想要执行后者。因为会有很多 static_casts

【讨论】:

    【解决方案2】:

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

    这不是微不足道的。您必须在每个特定类的开始/结束和每个派生迭代器中实现值访问函数、复制/比较等运算符。

    创建你的类型值(不是集合)的基类并将指向对象的指针存储在标准容器中不是更容易吗?

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

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

    在您的情况下,您在派生类中使用具有不同类型的不同容器。它只是一个例子,还是应该这样?如果是第二个,模板在这里将无济于事。

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

    还有一个问题,你会返回哪种类型?一种变体可能是一种解决方案。

    【讨论】:

    • begin() 怎么会返回 void?需要将迭代器返回到我认为的容器。
    • 我明白了。有接口,begin 重置集合(内部索引设置为内部容器的开始),getNext 返回下一个有效值并增加内部索引。所以这不是你想要的。然后你应该实现一个层次结构或迭代器,我认为。请。很快就会看到更新。
    猜你喜欢
    • 2013-01-15
    • 2017-02-14
    • 1970-01-01
    • 2021-08-08
    • 2015-03-26
    • 2023-04-11
    • 2019-02-11
    • 2017-04-06
    • 2016-08-13
    相关资源
    最近更新 更多