如何为基类泛型类型创建向量以使用具体类型元素

时间:2019-06-25 22:18:39

标签: c++ c++11 vector

如果sb。可以将标题更改为更容易理解的名称

这是我当前的实现方式:

std::vector<Zone<sf::CircleShape>*> allZones;                                          
std::vector<Zone<sf::CircleShape>*> estates = initializer->initVillageEstates();       
std::vector<Zone<sf::CircleShape>*> communityAreas = initializer->initCommunityAreas();

我很想吃这样的东西:

std::vector<Zone<sf::Shape>*> allZones;                                          
std::vector<Zone<sf::CircleShape>*> estates = initializer->initVillageEstates();       
std::vector<Zone<sf::RectangleShape>*> communityAreas = initializer->initCommunityAreas();

CircleShapeRectangleShape源自基类Shape。我认为,如果矢量类似于vector的通用类型,而不是矢量的通用类型的通用类型,则对矢量来说是可行的。

想到的一种解决方案是,我使Zone不是模板类,而是像ZoneShapeZoneCircle : public ZoneShapeZoneRectangle : public ZoneShape一样。

这样我就可以做到这样:

std::vector<ZoneShape*> allZones;                                          
std::vector<ZoneCircle*> estates = initializer->initVillageEstates();       
std::vector<ZoneRectangle*> communityAreas = initializer->initCommunityAreas();

我认为这可行,但是我发现模板更符合我的目的。所以我必须弄清楚这可能如何工作。

1 个答案:

答案 0 :(得分:1)

要回答您的总体问题,没有C ++的方法可以自动使模板遵循其类型参数的继承规则(某些其他语言,例如Scala可以让您做到这一点,但它们通常也不适用于值类型)。就C ++而言,类型A的向量与类型B的向量是完全独立的类型,即使它们都是相同模板的子代。

听起来,您似乎意识到了这一点。就替代方案而言,为您可能想添加的每个形状创建单独的ZoneShape类是乏味的(并且违反了DRY),所以我们不要这样做。但是,如果普通的旧模板不按照您想要的方式支持继承,并且使更多的类继承过于重复,则可以同时利用两个世界:

class ZoneShape {
    // Not sure what your Zone class needs to do,
    // but include your functionality based on the
    // base Shape class here.
public:
    virtual void setShape(Shape* shape) = 0;
    virtual Shape* getShape() = 0;
};

template<typename T>
class Zone : public ZoneShape {
protected:
    // Implemented versions of the base type.
    void setShape(Shape* shape) override;
    Shape* getShape() override;

public:
    // Specific to your specific type.
    void setShape(T* t);
    T* getSpecificShape(); // EDIT: This was originally "T* getShape()", 
                           // which cannot be overloaded.
};

std::vector<ZoneShape*> allZones;                                          
std::vector<Zone<sf::CircleShape>*> estates = initializer->initVillageEstates();       
std::vector<Zone<sf::RectangleShape>*> communityAreas = initializer->initCommunityAreas();

这并不完美(例如Zone<SquareShape>*不一定与Zone<RectangleShape>*堆叠),但是它应该允许您同时拥有适用于所有形状类型区域的通用容器以及针对特定形状的更专门的容器形状。