C ++ - 基本容器问题

时间:2010-08-03 12:25:34

标签: c++ storage containers

如何处理以下案件:

我有一些几何存储,它是顶点类型的template

template <typename T> struct Geometry {

std::vector<T>& GetVertices() { ... }

const void* RawVertices() const { ... }

}

除非我想在一个容器中存储不同类型的几何(例如,Geometry<Vertex1> g1Geometry<Vertex2> g2,否则这样可以正常工作。

这可能吗?

或者我应该如何实现几何存储(我可以使用一个容器存储和检索不同类型的几何)或者可能以某种方式将T类型映射到Geometry<T>类型?

有任何建议吗?

谢谢。

4 个答案:

答案 0 :(得分:3)

由于GetVertices只返回Vertex类型的对象,我建议你从泛型转向面向对象的设计。

class Vertex
{
   ....
};

class Vertex1 : public Vertex 
{
   ....
};

class Vertex2 : public Vertex 
{
   ....
};

typedef std::vector<Vertex*> Vertices;

struct Geometry
{
    const Vertices& GetVertices() const { .... }
    ....
};

答案 1 :(得分:2)

由于容器与其可以包含的一种数据类型相关联,因此您可以创建一个类GeometryBase,从中派生所有Geometry<T>,然后存储GeometryBase 指针< / strong>在你的容器中。

struct GeometryBase
{
    // Non-template methods might go here.
    // Don't forget to declare the base class destructor virtual.
};

template <typename T> struct Geometry : public GeometryBase
{
    // Template methods go here
};

编辑:
在某些时候,你将不得不决定你想要获得哪种类型的顶点容器(我的方法)你想用顶点做什么(Vijay Mathew的方法),然后你将不得不使用dynamic_cast&lt ;&GT;以便访问派生类方法。

另一个建议:
如果类型与您在评论中描述的类型不同,那么将它们视为不同的类型实际上可能更好 例如,您可以为每个Geometry<>模板实例创建一个单独的容器。

class SomeStorageClass
{
/* ... */
private:
    std::vector< Geometry<Vertex1> > m_vertex1Geometries;
    std::vector< Geometry<Vertex2> > m_vertex2Geometries;
};

如果你有一些函数可以在一种几何上运行(使用Vertex1::GetPos(),使用你的例子)或另一种(Vertex2::GetUV()),那么这些函数的实现可能完全不同,因此应该是期望不同类型参数的单独函数。

答案 2 :(得分:1)

异构容器(即存储多种类型的对象)引入了很多问题 - 一个明显的例子,当你检索一个对象时,你必须做些什么来弄清楚你是哪种对象检索。

C ++中内置的容器采用简单的路径:它们是同构的 - 它们只存储一种类型的对象。如果你想存储两种不同类型的对象,你可以将它们包装到你存储在容器中的第三种类型中(通常还有一些东西来指示特定对象的确是哪种类型)。例如,你可以这样做:

class vertex1 {};

class vertex2 {};

class vertex {
    vertex1 *v1;
    vertex2 *v2;
public:
    vertex(vertex1 *init1) : v1(init1), v2(NULL) {}
    vertex(vertex2 *init2) : v1(NULL), v2(init2) {}
};

std::vector<vertex> vertices;

当然,有很多变化(例如,存储指向基类的指针),但最终归结为一件事:集合本身持有一种类型的对象,并且该类型以某种方式或其他方式管理你需要处理的其他两种类型。

答案 3 :(得分:1)

class IGeometry
{
public:
    virtual const void* RawVertices() const = 0;
    virtual ~IGeometry() {}

    template <typename T>
    std::vector<T>& GetVertices() const 
    { 
        typedef const Geometry<T>* AppropriateDerivedClass;
        return dynamic_cast<AppropriateDerivedClass>(this)->GetVertices();
    };
};