可能的循环依赖? c ++

时间:2018-11-19 21:12:41

标签: c++ struct circular-dependency

我有一个Vulkan项目,该项目使用的模型管理器基于我的教授编写的模型管理器。在这个模型管理器中,我Model.h #include分别将Mesh.h#includevulkan/vulkan.h#include到{{ 1}}。在外部,它们都引用了我的包装的静态全局实例,用于我的引擎的呈现部分。在我的Google搜索过程中,我得出的初步结论是我具有循环依赖关系。我希望有人能为我指出这一点。

Model.h

Texture.h

Texture.h

#pragma once

#include <vector>
#include <vulkan/vulkan.h>

#include "Texture.h"
#include "Mesh.h"

struct Model
{
    uint8_t                             _inuse;
    uint32_t                            _refcount;
    TextLine                            filename;
    Mesh                                *mesh; //C4430 & C2143
    Texture                             *texture; //C4430 & C2143
    VkDescriptorPool                    descriptorPool;
    std::vector<VkDescriptorSet>        descriptorSets;
    uint32_t                            descriptorSetCount;

void DrawModel(Model *model, uint32_t bufferFrame, VkCommandBuffer 
     commandBuffer);
};

class Model_Manager
{
private:
    std::vector<Model>      model_list;
    uint32_t                modelMax;

public:

    uint32_t                swapchainLength;
    VkDevice                logDevice;
    VkPhysicalDevice        physDevice;
    VkDescriptorSetLayout   descriptorSetLayout;

    void Model_ManagerInit(uint32_t maxModels, uint32_t chainLength, 
         VkDevice device, VkPhysicalDevice physicalDevice);

    Model* NewModel();
    Model* GetModelByFilename(char *filename);
    Model LoadModel(char * filename);
    void DeleteModel(Model *model);

    VkDescriptorSetLayout* GetModelDescriptorSetLayout(){ return 
&descriptorSetLayout; }

    static void CreateDescriptorPool(Model *model, VkDevice device);
    static void CreateDescriptorSets(Model *model);
    static void CreateDescriptorSetLayout(Model *model, VkDevice device);
    static void ModelSetup(Model *model, VkDevice lDevice);
};

extern Model_Manager modelManager;

Mesh.h

#pragma once

#include <vector>

#include "gf3d_text.h"
#include "Vulkan_Graphics.h"

struct Texture
{
    uint8_t             _inuse;
    uint32_t            _refcount;
    TextLine            filename;
    VkImage             textureImage;
    VkDeviceMemory      textureImageMemory;
    VkImageView         textureImageView;
    VkSampler           textureSampler;
    };


class Texture_Manager
{ 
private:
    uint32_t                textureMax;
    VkDevice                logDevice;

public:
    std::vector<Texture>    textureList;

    void Texture_ManagerInit(uint32_t maxTextures, VkDevice lDevice);

    static Texture* LoadTexture(char *filename);
    static Texture* GetTextureByFilename(char * filename);
    static void CopyBufferToImage(VkBuffer buffer, VkImage image, uint32_t 
width, uint32_t height);
    static Texture* NewTexture();
    static void CreateTextureSampler(Texture *tex, VkDevice device);
    static void DeleteTexture(Texture *tex, VkDevice device);
};

extern Texture_Manager textureManager;

Vulkan_Graphics.h

#pragma once

#include "gf3d_text.h"
#include "Vulkan_Graphics.h"

struct Vertex
{
    glm::vec3 vertex;
    glm::vec3 normal;
    glm::vec2 texel;
};

struct Face
{
    uint32_t  verts[3];
};

struct Mesh
{
    TextLine        filename;
    uint32_t        _refCount;
    uint8_t         _inuse;
    uint32_t        vertexCount;
    VkBuffer        buffer;
    VkDeviceMemory  bufferMemory;
    uint32_t        faceCount;
    VkBuffer        faceBuffer;
    VkDeviceMemory  faceBufferMemory;

    void MeshRender(Mesh *mesh, VkCommandBuffer commandBuffer, VkDescriptorSet 
*descSet);
};

class Mesh_Wrapper
{
   private:
     std::vector<Mesh>                  mesh_list;
     uint32_t                           maxMeshes;
     VkVertexInputAttributeDescription  attributeDescriptions[3];
     VkVertexInputBindingDescription        bindingDescription;
     std::vector<Command>               stagingCommandBuffer;
     VkDevice                           logDevice;
     VkPhysicalDevice                   physDevice;

public:
     Mesh_Wrapper();
     ~Mesh_Wrapper();

     void Mesh_WrapperInit(uint32_t meshCount, VkDevice logDevice, 
VkPhysicalDevice physDevice);

    Mesh* NewMesh();
    void DeleteMesh(Mesh* mesh);

    Mesh* LoadMesh(char *filename);
    Mesh* GetMeshByFilename(char *filename);


    VkVertexInputAttributeDescription* GetAttributeDescriptions(uint32_t 
  *count);
    VkVertexInputBindingDescription* GetBindDescription();

    static Mesh* LoadMesh(char * filename, Mesh_Wrapper *mWrapper);
    static void CreateVertexBufferFromVertices(Mesh *mesh, Vertex *vertices, 
uint32_t vcount, Face *faces, uint32_t fcount);
    static void SetupFaceBuffers(Mesh *mesh, Face *faces, uint32_t fcount);
};

extern Mesh_Wrapper meshManager;

2 个答案:

答案 0 :(得分:2)

我无法诚实地告诉您是否具有循环依赖关系,但是您拥有.h文件(包括其他.h文件)的事实使它有一定的可能性。我可以告诉你如何避免。

当您为类声明 pointer reference 时,您不需要完整的类定义。前瞻性声明可以。在您的Model.h中,不必包含Texture.hMesh.h。将它们替换为前向声明:

struct Texture;
struct Mesh;

您需要确保在实际尝试使用这些指针的源文件中包含这些标题。

答案 1 :(得分:0)

您对文件有循环依赖关系,该依赖关系应由#pragma once语句破坏。该语句保证include文件在编译中仅包含一次。因此,如果Mesh.h已包含在Model.h中,并且首先编译了Mesh.h,则尽管它已包含在Vulkan_Graphics.h中,也不会再次编译。

但是,问题在于此编译指示不是标准的编译指示,某些编译器可能不支持该编译指示。因此,保护​​文件免受多个包含内容和导致循环依赖的可能性的标准方法是使用保护宏来保护文件,即

#ifndef MY_HEADER_FILE
#define MY_HEADER_FILE
... header file contents ...
#endif

缺点是您必须确保宏名称在所有编译文件中都是唯一的,通常将文件名用作其模板。