【问题标题】:templates vs switch模板与开关
【发布时间】:2011-03-06 08:58:06
【问题描述】:

我正试图在 C++ 领域找到自己的方式,但现在越来越困惑。玩具应用程序是一个非常基本的 OpenGL 引擎。 所以这是(我猜很简单)问题: 我想处理不同顶点数据的网格,所以我有例如

struct Vertex
{
    Vector3f position;
}

struct VertexN : public Vertex
{
    Vector3f normal;
}

现在我需要一个 Mesh 类来保存数据并进行绘制。 我尝试过这样的事情:

template<class T>
class Mesh
{
    public:
        Mesh();
        ~Mesh();

        void load(const T * vertices, int num);
        void draw();

    protected:
        T * vertices_;

};

不同的顶点必须以不同的方式加载和绘制,这可以通过模板专业化来完成。

我的问题是我喜欢拥有另一个包含 Mesh 对象实例的类,但显然不允许使用模板化的类成员。

我能想到的另一个解决方案是在 Mesh 中保存指向基本结构 Vertex 的指针,传递所用 Vertex 类型的标识符,然后在 load() 和 draw() 中使用 switch 语句以允许不同的实现。

最好的方法是什么?

非常感谢任何帮助。

【问题讨论】:

    标签: c++


    【解决方案1】:

    您可以使用继承和虚函数。例如:

    class MeshBase
    {
    public:
        virtual ~MeshBase() { }
        virtual void draw() = 0;
    };
    
    template <typename T>
    class Mesh : public MeshBase
    {
    public:
        virtual void draw() { }
        // ...
    };
    

    通过这种方法,您可以将指向基类MeshBase 的指针存储在容器中。

    理想情况下,您可以使用指针容器,它会为您管理指针,或者您可以使用智能指针容器(例如,std::vector&lt;std::shared_ptr&lt;MeshBase&gt; &gt;,如果您的实现包含shared_ptr;如果没有,@ 987654321@).

    我还建议将顶点存储在 Mesh 类的容器中,而不是使用手动动态分配和内存管理。

    【讨论】:

    • 考虑到 Vertex 类的继承,Mesh 上的模板是否也可以移除?
    • @drfrogsplat:仅当您想存储指向单个顶点的指针时,出于性能原因可能不希望这样做。我根本不会对顶点类使用继承:只需将每种类型的顶点实现为独立类或使用模板(例如,OpenSceneGraph 就是这样做的)。
    • 如果您可以访问 boost(它是 Boost.PointerContainer 的一部分),请尝试更喜欢 boost::ptr_vector 而不是 std::vector&lt;boost::shared_ptr&gt;。在 C++0x 中,您可以使用 std::vector&lt;unique_ptr&gt; 来避免 boost 依赖。
    • @James:我知道解决方案一定很简单,谢谢!我还将删除 Vertex 结构中的继承。关于将顶点存储在 std::vector 中:是否仍然可以使用 offsetof() 宏访问 Vertex 的不同成员?
    • @matthieu:是的,学习提升是我的待办事项,我会记住这一点
    【解决方案2】:

    我建议您不要将网格类模板化,而是使其能够处理不同类型的顶点数据。这是一个常见的图形问题,在 DirectX 中通过将不同的数据“流”绑定在一起以绘制几何图形的概念得到解决。换句话说,您的法线将是与您的位置数据不同的数据流。然后,您的网格对象成为多个数据流的容器,并且在编译时不会绑定到特定的顶点格式。我也不了解 OpenGL,但我想有一个类似的概念。

    见:http://msdn.microsoft.com/en-us/library/bb147299(VS.85).aspx

    【讨论】:

      【解决方案3】:

      @bshields 有一点,你需要以最有效的方式表示顶点数据,在 OpenGL 的情况下是 Vertex Buffer Objects (VBO):http://www.opengl.org/wiki/Vertex_Buffer_Object

      鉴于上面链接中公开的指南 - 这与 @James McNellis 所说的关于不为您的顶点类型使用继承的说法一致 - 并且加载和绘图都可能取决于顶点的类型和类型输入(或输出)我建议您使用静态多态性应用策略模式,如另一个问题的答案中所述:template strategy pattern

      【讨论】:

      • 谢谢。 draw() 已经使用了 VBO 的包装器。我还应该正确对齐数据...您链接的帖子很有趣,但现在对我来说似乎有点矫枉过正。反正已经收藏了。
      猜你喜欢
      • 2010-12-17
      • 2011-08-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多