Разработка дизайна интерфейса C ++ (чистый виртуальный класс) / множественное наследование / виртуальное наследование

Я хочу восстановить свой маленький 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? ок, это безумие !!!

я думаю, это abime.
какая ошибка в этом дизайне? Как изменить дизайн идеи, чтобы избежать этой дилеммы? знаете ли вы идею, которая может сохранить иерархию наследования этих интерфейсов и легко реализовать?
если я использую много виртуального наследования, есть ли производительность?

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;
}
};
...

Для производительности последствия этого, посмотрите на этот вопрос.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]