如何处理以下案件:
我有一些几何存储,它是顶点类型的template
。
template <typename T> struct Geometry {
std::vector<T>& GetVertices() { ... }
const void* RawVertices() const { ... }
}
除非我想在一个容器中存储不同类型的几何(例如,Geometry<Vertex1> g1
和Geometry<Vertex2> g2
,否则这样可以正常工作。
这可能吗?
或者我应该如何实现几何存储(我可以使用一个容器存储和检索不同类型的几何)或者可能以某种方式将T
类型映射到Geometry<T>
类型?
有任何建议吗?
谢谢。
答案 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();
};
};