多种数据类型的C ++列表。继承?

时间:2017-07-10 02:34:25

标签: c++ types

我有很多不同的课程。但是,它们都保证具有某些方法,例如render()和activate()。

我的目标是能够将它们全部存储在一个大清单中。目前我有一个名为Container的大类,我做这样的事情来存储我拥有的许多对象。

class Container{
public:

  BUTTON * buttons;
  int buttons_len;

  DRAW_AREA * draw_areas;
  int draw_areas_len;

  Container(){
      // constructor
  }

  void render(){
      for( int i = 0; i < buttons_len; i++ )
          buttons[i].render();

      for( int i = 0; i < draw_areas_len; i++ )
          draw_areas[i].render();
  }

};

这个问题是,每次我想添加一个新的数据类型时,我都要修改多个区域,将来会变得难以处理。这是一个很好的方法吗?

我已经研究过使用模板,从我看到的,我不能在同一个列表中存储具有不同“模板变量”的类。

编辑:忘了提到渲染函数可以是不同的渲染函数。

编辑2:

我得到了我想要的工作。不确定“好代码”有多好,

以下是一个例子:

// abstract class
class Base{
public:
    virtual void render() = 0;
};


class Button : public Base{
public:
    int y;

    Button(){
        y = 10;
    }

    void render(){
        std::cout << "BUTTONS " << y << "\n";
    }

};


class Draw_Area : public Base{
public:
    int x;

    Draw_Area(){
        x = 5;
    }

    void render(){
        std::cout << "DRAW AREA " << x << "\n";
    }

    void extra(){
        std::cout << "extra draw_area\n" << x << "\n";
    }
};



int main( int argc, char * * argv ){

    Base * test_1 = new Button();
    test_1->render();

    Base * test_2 = new Draw_Area();
    test_2->render();   


    Base * * test = new Base*[4];

    test[0] = new Button();
    test[1] = new Button();
    test[2] = new Draw_Area();
    test[3] = new Button();


    test[0]->render();
    test[1]->render();
    test[2]->render();
    test[3]->render();


    return 0;
}

感谢您的帮助!我必须处理的主要两个问题是创建一个抽象类来避免对象切片,并将指针存储到类而不是列表中的对象本身。

2 个答案:

答案 0 :(得分:-1)

我有一个使用现代OpenGL的Game-Shader Engine。该项目有许多组件集成在一起。使用的一件事是一系列Manager Class对象,它们本身都是Singleton对象:

我无法向您展示完整的类,但我将展示包含所有派生单例类型的Singleton基类的枚举:

class Singleton {
public:
    // Number Of Items In Enum Type Must Match The Number
    // Of Items And Order Of Items Stored In s_aSingletons
    enum SingletonType {
        TYPE_LOGGER = 0, // MUST BE FIRST!
        TYPE_SETTINGS,
        TYPE_ENGINE,
        TYPE_ANIMATION_MANAGER,
        TYPE_SHADER_MANAGER,
        TYPE_ASSET_STORAGE,
        TYPE_AUDIO_MANAGER,
        TYPE_FONT_MANAGER,
        TYPE_BATCH_MANAGER,     
    }; // Type;

    // More code below
}; // Singleton

这些是我们在应用程序或游戏的生命周期中只需要一个实例的对象。

现在关于你的例子和问题,上面列表中与你想要达到的目标相关的重要性是:

  • ShaderManager
  • AssetStorage
  • 批处理管理

我们可以忽略其他人,因为我们并不担心AudioFontsAnimationsGame SettingsThe Main Game Engine和{{ 1}}虽然它们是通过上面列出的一些对象使用的。

上面的3以这样的方式集成,即Logger类将保存要呈现的所有对象的容器。 AssetStorage还包含其他重要的东西,如加载的纹理,字体,音频文件,gui控件精灵,模型等。AssetStorage类的目的是它充当负责的数据库用于管理这些对象的所有内存。

发送要呈现的所有顶点数据是AssetStorage的责任,这是基于优先级队列的工作,其中优先级队列由哪个BatchManager's最充分或具有{ {1}}该优先级基于Batch。当highest priority准备发送顶点数据(如属性和制服,矩阵等)时,它会查看Z-Depth以查看要应用于准备渲染顶点的Shader技术,然后它设置了属性和制服。

这是一只非常复杂的野兽;这也不是唯一的方法,因为有其他方法,特别是当你开始渲染3D Terrains并且你必须构建一个场景图,BSP,体素,行进立方体等。

如果您想了解有关上述技术的更多信息,可以访问Marek Knows并关注他的OpenGL视频教程系列。然而,上面描述的方法正在使用Modern OpenGL,你必须遵循他早期使用Deprecated - Legacy OpenGL 1.0的系列,因为他就是如何设置他的网站。

我能做的是向您展示BatchManager标题文件中的一小段摘录,以便您可以看到此类&#34;商店&#34;的容器和方法。和&#34;管理&#34;游戏对象的记忆或者#34;资产&#34;。

<强> AssetStorage.h

ShaderManager

我还可以向您展示Asset Storage's&amp;的声明。 #ifndef ASSET_STORAGE_H #define ASSET_STORAGE_H #include "Singleton.h" #include "CommonStructs.h" namespace vmk { class BaseMko; class GuiElement; enum GuiType; struct Texture { bool hasAlphaChannel; bool generateMipMap; bool wrapRepeat; unsigned uWidth; unsigned uHeight; TextureInfo::FilterQuality filterQuality; std::vector<unsigned char> vPixelData; Texture( TextureInfo::FilterQuality filterQualityIn, bool generateMipMapIn, bool wrapRepeatIn ) : hasAlphaChannel( false ), generateMipMap( generateMipMapIn ), wrapRepeat( wrapRepeatIn ), uWidth( 0 ), uHeight( 0 ), filterQuality( filterQualityIn ) {} }; // Texture class AssetStorage sealed : public Singleton { private: typedef std::unordered_map<std::string, std::shared_ptr<BaseMko>> MapMkoAssets; typedef std::unordered_map<std::string, TextureInfo> MapTextureInfos; typedef std::unordered_map<std::string, std::shared_ptr<GuiElement>> MapGuiAssets; MapMkoAssets m_mkoAssets; MapTextureInfos m_textureInfos; MapGuiAssets m_guiScreenAssets; MapGuiAssets m_guiRenderableAssets; std::vector<std::string> m_vGuiForRemoval; public: AssetStorage(); virtual ~AssetStorage(); static AssetStorage* const get(); // Mko Objects BaseMko* getMko( const std::string& strId ) const; void add( BaseMko* pMko ); bool removeMko( const std::string& strId, bool removeTexture = false ); void showLoadedMkoObjects() const; // Texture Objects TextureInfo getTextureInfo( const std::string& strFilename ) const; TextureInfo add( const Texture& texture, const std::string& strFilename ); bool removeTextureInfo( const std::string& strFilename ); bool removeTextureInfo( unsigned uTextureId ); void showLoadedTextureInfo() const; // Gui Objects GuiElement* getGuiElement( const std::string& strId, GuiType type ) const; void add( GuiElement* pGui, GuiType type ); bool removeGuiElement( const std::string& strId, bool removeTextures = false ); template<typename T> bool removeGuiElement( T* pGui, bool removeTextures = false ); void markGuiForRemoval( const std::string& strId ); void cleanOrphanedGuiObjects(); void showLoadedGuiObjects() const; private: AssetStorage( const AssetStorage& c ); // Not Implemented AssetStorage& operator=( const AssetStorage& c ); // Not Implemented // Gui Objects GuiElement* getGuiElement( const std::string& strId, const MapGuiAssets& guiMap ) const; void add( GuiElement* pGui, MapGuiAssets& guiMap ); bool removeGuiElement( const std::string& strId, MapGuiAssets& guiMap, bool removeTextures ); }; // AssetStorage } // namespace vmk #endif // ASSET_STORAGE_H 个类,但我无法向您展示 实施

<强> BatchManager.h

BatchManager

<强> ShaderManager.h

ShaderManager

正如您所看到的,这是一个非常复杂的对象系统,您提出的问题是一个非常广泛的问题,可以根据您的需要以多种方式完成。我刚刚提出这个问题,以展示一个人如何实现这一目标的概念。

与上面的代码片段一样,您可以看到#ifndef BATCH_MANAGER_H #define BATCH_MANAGER_H #include "Singleton.h" #include "CommonStructs.h" namespace vmk { class Batch; class BatchManager sealed : public Singleton { private: std::vector<std::shared_ptr<Batch>> m_vBatches; unsigned m_uNumBatches; unsigned m_uMaxNumVerticesPerBatch; public: BatchManager( unsigned uNumBatches, unsigned uNumVerticesPerBatch ); virtual ~BatchManager(); static BatchManager* const get(); void render( const std::vector<GuiVertex>& vVertices, const BatchConfig& config, const std::string& strId ); void emptyAll(); private: BatchManager( const BatchManager& c ); // Not Implemented BatchManager& operator=( const BatchManager& c ); // Not Implemented void emptyBatch( bool emptyAll, Batch* pBatchToEmpty ); //void renderBatch( const std::vector<GuiVertex>& vVertices, const BatchConfig& confg ); }; // BatchManager } // namespace vmk #endif // BATCH_MANAGER_H 类中的不同类型的容器,然后当您查看#ifndef SHADER_MANAGER_H #define SHADER_MANAGER_H #include "Singleton.h" #include "ShaderProgramSettings.h" namespace vmk { class ShaderManager sealed : public Singleton { private: // Number Of Items In enum type Must Match The Number Of Items // Stored In s_aShaders And In InfoProgram::aShaderIndex enum ShaderType { TYPE_VERTEX = 0, TYPE_FRAGMENT, }; // ShaderType struct AttributeVariable{ unsigned uLocation; AttributeType eType; int iSize; AttributeVariable( AttributeType eTypeIn, unsigned uLocationIn ); }; // AttributeVariable struct UniformVariable{ unsigned uLocation; UniformType eType; UniformVariable( UniformType eTypeIn, unsigned uLocationIn ); }; // UniformVariable typedef std::unordered_map<Attribute, AttributeVariable> MapAttributes; typedef std::unordered_map<Uniform, UniformVariable> MapUniforms; struct InfoProgram{ unsigned uId; std::array<unsigned, 2> aShaderIndex; MapAttributes mAttributes; MapUniforms mUniforms; InfoProgram(); }; // InfoProgram struct InfoShader{ unsigned uId; std::string strFilename; InfoShader( int iOpenglSharedId, std::string strShaderFilename ); }; // InfoShader typedef std::shared_ptr<InfoProgram> SharedInfoProgram; typedef std::shared_ptr<InfoShader> SharedInfoShader; typedef std::vector<SharedInfoProgram> VectorInfoPrograms; typedef std::vector<SharedInfoShader> VectorInfoShaders; VectorInfoPrograms m_vPrograms; std::array<VectorInfoShaders, 2> m_avShaders; Program m_eEnabledShaderProgram; unsigned m_uActiveTextureNumber; public: ShaderManager(); virtual ~ShaderManager(); static ShaderManager* const get(); void create( ShaderProgramSettings& shaderProgramSettings ); void enable( Program eShaderProgram ); void enableAttribute( Attribute eShaderAttribute, unsigned strideBytes = 0, unsigned offsetBytes = 0, bool normalize = false ) const; void disableAttribute( Attribute eShaderAttribute ) const; void setAttribute( Attribute eShaderAttribute, const glm::vec4& v4Value ) const; void setUniform( Uniform eShaderUniform, const glm::mat4& m4Matrix ) const; void setUniform( Uniform eShaderUniform, const float fValue ) const; void setUniform( Uniform eShaderUniform, unsigned uValue ) const; void setUniform( Uniform eShaderUniform, bool bValue ) const; void setTexture( unsigned uTextureNumber, Uniform eSamplerUniform, int iTextureId ); private: ShaderManager( const ShaderManager& c ); // Not Implemented ShaderManager& operator=( const ShaderManager& c ); // Not Implemented unsigned initializeShader( ShaderType eType, const std::string& strShaderFilename ); void processAttributes( unsigned uInfoProgramId, Program eShaderProgram, std::vector<ShaderProgramSettings::AttributeInfo>& vAttributes, MapAttributes& mAttributes ) const; void processUniforms( unsigned uInforProgramId, Program eShaderProgram, std::vector<ShaderProgramSettings::UniformInfo>& vUniforms, MapUniforms& mUniforms ) const; template<typename T> void setVertexAttribute( Attribute eShaderAttribute, const T* const pParam, bool bEnable, unsigned strideBytes, unsigned offsetBytes, bool normalize ) const; void setVertexAttribute( AttributeVariable attrib, const void* const pVoid, bool bEnable, unsigned strideBytes, unsigned offsetBytes, bool normalize ) const; void setVertexAttribute( AttributeVariable attrib, const float* p4Values, bool _x1_, unsigned _x2_, unsigned _x3_, bool _x4_ ) const; }; // ShaderManager #include "ShaderManager.inl" } // namespace vmk #endif // SHADER_MANAGER_H 类时,您可以看到原型的函数来渲染由AssetStorageBatchManager以及render()完成的顶点。

尝试拥有每一个&#34;对象&#34;是完全不明智的。有自己的&#34;渲染&#34;功能。每个对象只需要担心它的emptyBatch()emptyAll()应该由Attributes & Properties负责使用这些类来了解何时最有效和时间通过GameEngine渲染所述顶点然后应用适当的着色或颜色技术。

答案 1 :(得分:-2)

如果每个类都有一个render()函数,而你想用一个命令调用所有这些函数,那么你可以这样做。

class outer
{
public:
    outer(); // Constructor.
    render();

private:
    other_class1 in_class1;
    other_class2 in_class2;
};

outer::render()
{
    in_class1.render();
    in_class2.render();
    // For all other member classes.
}

然后,您可以调用外部类outer.render()的render函数,该函数调用所有成员类的render()函数。