【问题标题】:A design qustion about C++ interface(pure virtual class)/multiple inheritance/virtual inheritanceC++接口(纯虚拟类)/多重继承/虚拟继承的设计问题
【发布时间】:2012-10-11 11:38:28
【问题描述】:

我想重建我的小型 3d 引擎,它非常小,所以我将所有文件放在一个项目中。 现在,我想用接口重建它,这样我就可以将不同的模块分散到不同的项目中,并将它们构建为 dll。 当我这样做时,我在框架代码的基本设计中遇到了很多困难。 我想为我的小引擎设计一个“对象层次结构”,它在之前的工作中实现了。例如:

Object
Component
SceneComponent
StaticMeshComponent/SkelMeshComponent
D3DSkelComponent 
...

但它们是直接实现的。 现在,我想使用接口(纯虚拟类),我已经设计了基本接口(用于测试):

#include <cstdio>
#include <iostream>
#include <string>
using namespace std;

class IObject
{
public:
    virtual std::string GetName() = 0;
};

class IMesh : public IObject
{
public:
    virtual void Draw() = 0;
};

class IStaticMesh : public IMesh
{
public:    
    virtual void BuildSomeMesh() = 0;
};

class ISkeletalMesh : public IMesh
{
public:
    virtual void PlayAnim( const std::string& strAnimName ) = 0;
};

class ID3DSkeletalMesh : public ISkeletalMesh
{
public:
    virtual void LoadD3D( const std::string& strD3D ) = 0;
};

看起来不错,但是当我尝试实现它们时,我发现这可能是一个不可能完成的任务。 首先,我可以为IObject写一个模板类或普通类,例如:

template < typename TBase >
class TObject : public TBase
{
public:
    virtual std::string GetName()
    {
        return m_strTest;
    }

    std::string m_strTest;
};

基于这个TObject,我可以实现一个CMesh:

class CMesh : public TObject< IMesh >
{
public:
    virtual void Draw()
    {
        cout<<"draw mesh" <<endl;
    }
};
   IMesh* pMesh = new CMesh();  // ok
   IObject* pObj = pMesh;      // ok

到目前为止,它运作良好。但是如何实现 CStaticMesh/CSkeletalMesh/CD3DSkeletalMesh? 可能是这样的:

class CStaticMesh : public CMesh, public IStaticMesh
{
public:

};

但我有两个 IObject 基类,所以我必须将所有“public xxx”更改为“virtual public xxx”,看起来很糟糕。 另一个问题是CStaticMesh必须实现IStaticMesh的所有虚成员函数,包括:

virtual void Draw() = 0;
virtual void BuildSomeMesh() = 0;

即使 CMesh 中有一个 Draw,它是 CStaticMesh 的基本调用。 好的,也许我需要一个 TMesh:

template < typename TBase >
class TMesh : public TObject< TBase >
{
public:
    virtual void Draw()
    {
        cout<<"draw mesh" <<endl;
    }
};

并像这样实现 CStaticMesh:

class CStaticMesh : public TMesh<IStaticMesh>
{
public:
    virtual void BuildSomeMesh()
    {
        cout<<"Build Some Mesh!"<<endl;
    }
};

看起来不错,但是如何实现 CD3DSkeletalMesh?制作一个 TSkeletalMesh?好吧,太疯狂了!!!

我想,这太棒了。 这个设计中的错误是什么?如何改变设计思路来避免这种困境?您知道可以保持这些接口的继承层次结构并轻松实现的想法吗? 如果我使用许多虚拟继承,是否有任何性能问题?

【问题讨论】:

    标签: c++ interface multiple-inheritance virtual-inheritance pure-virtual


    【解决方案1】:

    正如您所提到的,您可以使用虚拟继承来解决这个问题。这只会在层次结构中创建一个多重继承接口类的实例。

    首先是接口:

    class IObject
    {
    public:
        virtual std::string GetName() = 0;
    };
    
    class IMesh : virtual public IObject
    {
    public:
        virtual void Draw() = 0;
    };
    
    class IStaticMesh : virtual public IMesh
    {
    public:    
        virtual void BuildSomeMesh() = 0;
    };
    
    class ISkeletalMesh : virtual public IMesh
    {
    public:
        virtual void PlayAnim( const std::string& strAnimName ) = 0;
    };
    
    class ID3DSkeletalMesh : virtual public ISkeletalMesh
    {
    public:
        virtual void LoadD3D( const std::string& strD3D ) = 0;
    };
    

    然后是实现:

    class CObject : virtual public IObject
    {
    public:
        std::string GetName()
        {
            return m_strTest;
        }
    
        std::string m_strTest;
    };
    
    class CMesh : public CObject, virtual public IMesh
    {
    public:
        void Draw()
        {
            cout<<"draw mesh" <<endl;
        }
    };
    
    class CStaticMesh : public CMesh, virtual public IStaticMesh
    {
    public:
        void BuildSomeMesh()
        {
            cout<<"Build Some Mesh!"<<endl;
        }    
    };
    ...
    

    关于这对性能的影响,请查看this question

    【讨论】:

      猜你喜欢
      • 2014-11-06
      • 2017-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-19
      • 1970-01-01
      • 2011-10-15
      • 2015-11-21
      相关资源
      最近更新 更多