1

我想重建我的小型3D引擎,它非常小,因此我只将所有文件放在一个项目中。 现在,我想用接口重构它,所以我可以将不同的模块分散到不同的项目中,并将它们构建为一个dll。当我这样做时,我在框架代码的基本设计中遇到了很多困难。 我想设计一个我的小型引擎的“对象层次结构”,它是在以前的工作中实现的。例如:关于C++接口(纯虚拟类)/多继承/虚继承的设计问题

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提取,如:在此基础上TObject的

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

    std::string m_strTest; 
}; 

,我可以实现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提取的基类,所以我必须改变所有的“公共XXX”到“虚拟公共XXX”,这很糟糕。 另一个问题是CStaticMesh必须实现IStaticMesh的所有虚拟成员函数,包括:

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

即使在CMesh平局是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; 
    } 
}; 

看起来不错,但如何implment CD3DSkeletalMesh?做一个TSkeletalMesh?好的,这太疯狂了!

我想,这是abime。 这是这个设计中的错误吗?如何改变设计理念以避免这种困境?你知道一个可以保持这些接口的继承层次并轻松实现的想法吗?如果我使用许多虚拟继承,有没有什么性能isuue?

回答

0

你可以用虚拟继承来解决这个问题。这将只在层次结构中创建多个继承的接口类的一个实例。

首先接口:

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