【问题标题】:Possible circular dependency? c++ [duplicate]可能的循环依赖? C++ [重复]
【发布时间】:2018-11-19 21:12:40
【问题描述】:

我有一个 Vulkan 项目,它使用基于我教授编写的模型管理器的模型管理器。在这个模型管理器中,我有 Model.h#includeMesh.h#includevulkan/vulkan.h,以及 #includeTexture.h。在外部,它们都引用了我的引擎渲染部分的包装器的静态全局实例。在我的谷歌搜索过程中,我得出的初步结论是我有一个循环依赖。我希望有人可以为我指出这一点。

模型.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;

纹理.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;

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

Vulkan_Graphics.h

#pragma once

#include <vulkan/vulkan.h>
#include <iostream>
#include <glm/glm.hpp>

#include "Pipeline_Wrapper.h"
#include "GLFW_Wrapper.h"
#include "Extensions_Manager.h"
#include "Swapchain_Wrapper.h"
#include "Queue_Wrapper.h"
#include "Commands_Wrapper.h"
#include "Mesh.h"
#include "Texture.h"
#include "Model.h"

typedef struct
{
    glm::mat4 model;
    glm::mat4 view;
    glm::mat4 proj;
}UniformBufferObject;

class Vulkan_Graphics
{
private:
    VkInstance                      vkInstance;

    Command                         *graphicsCommandPool;

    VkDebugUtilsMessengerEXT        callback;
    VkSurfaceKHR                    surface;

    uint32_t                        deviceCount;
    VkPhysicalDevice                *devices;
    bool                            logicalDeviceCreated;

    VkQueue                         graphicsQueue;
    VkQueue                         presentQueue;
    VkQueue                         transferQueue;

    VkDeviceQueueCreateInfo         *queueCreateInfo;
    VkPhysicalDeviceFeatures        deviceFeatures;

    VkSemaphore                     imageAvailableSemaphore;
    VkSemaphore                     renderFinishedSemaphore;

    std::vector<VkLayerProperties>  validationAvailableLayers;
    std::vector<const char*>        validationInstanceLayerNames;
    std::vector<const char*>        validationDeviceLayerNames;

    std::vector<VkBuffer>           uniformBuffers;
    std::vector<VkDeviceMemory>     uniformBuffersMemory;
    uint32_t                        uniformBufferCount;

   void CreateVulkanInstance();
    void CreateLogicalDevice();

    void CreateSemaphores();

    void CreateUniformBuffer();

    void SetupDebugCallback();

    bool CheckValidationLayerSupport();

    void PickPhysicalDevice();

    VkDeviceCreateInfo GetDeviceInfo(bool validation);

    VkPhysicalDevice GetPhysicalDevice(){ return physicalDevice; }

    bool IsDeviceSuitable(VkPhysicalDevice device);

public:
   GLFW_Wrapper                 *glfwWrapper;
    Commands_Wrapper                *cmdWrapper;
    Extensions_Manager              *extManager;
    Queue_Wrapper                   *queueWrapper;
    Swapchain_Wrapper               *swapchainWrapper;
    Pipeline_Wrapper                *pipeWrapper;

    UniformBufferObject             ubo;

    Pipeline                        *currentPipe;

    VkPhysicalDevice                physicalDevice;
    VkDevice                        logicalDevice;

    Vulkan_Graphics(GLFW_Wrapper *glfwWrapper, bool enableValidation);
    ~Vulkan_Graphics();

    Command* GetGraphicsPool(){ return graphicsCommandPool; }
    Pipeline* GetCurrentPipe(){ return currentPipe; }
    VkQueue GetGraphicsQueue(){ return graphicsQueue; }

    VkFramebuffer VRenderBegin();
    void VRenderEnd();

    uint32_t BeginDrawFrame();
    void EndDrawFrame(uint32_t imageIndex);
    Command* GetGraphicsCommandPool(){ return graphicsCommandPool; }

    VkBuffer GetUniformBufferByIndex(uint32_t index);

    static int CreateBuffer(VkDeviceSize size, VkBufferUsageFlags usage, 
VkMemoryPropertyFlags properties, VkBuffer * buffer, VkDeviceMemory * 
bufferMemory);
    static uint32_t FindMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags 
properties, VkPhysicalDevice physicalDevice);
    static VkImageView CreateImageView(VkImage image, VkFormat format, VkDevice 
logDevice);
    static void CopyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, 
VkDeviceSize size, VkDevice lDevice, VkPhysicalDevice physDevice);

};

extern Vulkan_Graphics vGraphics;

【问题讨论】:

  • 不看"Vulkan_Graphics.h"的内容很难说。
  • 这里到底有什么问题?你有编译错误吗?
  • 是的,我收到了四个错误,两个关于在模型中包含网格,另外两个关于在模型中包含纹理。这两个错误是:C2143:语法错误:缺少';'在“*”之前 c:\users\ian\desktop\vulkan-laptop\vulkan-laptop\vulkan-laptop\include\model.h 错误 C4430:缺少类型说明符 - 假定为 int。注意:C++ 不支持 default-int c:\users\ian\desktop\vulkan-laptop\vulkan-laptop\vulkan-laptop\include\model.h 17 1 Vulkan-Laptop
  • Mesh.h 不应包括 Vulkan_Graphics.h 如果 Vulkan_Graphics.h 包括 Mesh.h

标签: c++ struct circular-dependency


【解决方案1】:

我不能诚实地告诉你是否或在哪里有循环依赖,但事实上你有 .h 文件,包括其他 .h 文件,这使得它成为一个明确的可能性。不过我可以告诉你如何避免它。

当你声明一个类的指针引用时,你不需要完整的类定义;一个前向声明就可以了。在您的Model.h 中不必包含Texture.hMesh.h。用前向声明替换它们:

struct Texture;
struct Mesh;

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

【讨论】:

    【解决方案2】:

    你对你的文件有一个循环依赖,它应该被#pragma once 语句破坏。该语句保证include 文件在编译中只包含一次。因此,如果 Mesh.h 包含在 Model.h 中,并且首先编译了 Mesh.h,那么尽管它已包含在您的 Vulkan_Graphics.h 中,但它不会再次编译。

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

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

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

    【讨论】:

    • 问题中引用的错误代码表明他们使用的是Microsoft Visual C++,它绝对支持#pragma once。所以需要不同的解释。
    猜你喜欢
    • 1970-01-01
    • 2018-04-21
    • 2014-01-28
    • 1970-01-01
    • 1970-01-01
    • 2012-04-24
    • 1970-01-01
    • 2016-10-02
    • 1970-01-01
    相关资源
    最近更新 更多