C++ 循环依赖,即使类是前向声明的

C++ 循环依赖,即使类是前向声明的,c++,visual-studio-2015,circular-dependency,C++,Visual Studio 2015,Circular Dependency,这里有一个非常奇怪的问题,即使向前声明受影响的类也无法解决循环依赖关系 如您所见,这两个类都是前向声明的。有什么解释吗?未定义任何类的符号。这显然是一个循环依赖错误 提前感谢您的建议 LogBackend.h #ifndef LOGGER_BACKEND_H #define LOGGER_BACKEND_H #include "Logger.h" #include <string> namespace se { class Logger; class LogBac

这里有一个非常奇怪的问题,即使向前声明受影响的类也无法解决循环依赖关系

如您所见,这两个类都是前向声明的。有什么解释吗?未定义任何类的符号。这显然是一个循环依赖错误

提前感谢您的建议

LogBackend.h

#ifndef LOGGER_BACKEND_H
#define LOGGER_BACKEND_H

#include "Logger.h"
#include <string>

namespace se {
    class Logger;
    class LogBackend {
    public:

        LogBackend() { }
        explicit LogBackend(const std::string& name);
        virtual ~LogBackend() { }

        virtual void log(const Logger::Level l, const std::string& text) = 0;

        /*
         Method interface
        */

        bool valid();
        std::string getName();

    protected:
        bool m_valid = true;
        std::string m_name;
    };
}
#endif
#ifndef LOGGER_H
#define LOGGER_H

#include "LogBackend.h"
#include <string>
#include <sstream>
#include <vector>
#include <glew/glew.h>

namespace se {
    class LogBackend;
    class Logger {
    public:

        enum class Level { WARNING, INFO, EXCEPTION, SEVERE };
        static std::string to_string(Level l);

        static void add(const LogBackend& backend);

        /*
         Methods
        */

    private:
        static std::vector<LogBackend> m_backends;
    };
}
#endif
\ifndef记录器\u后端\u H
#定义记录器\u后端\u H
#包括“Logger.h”
#包括
名称空间se{
类记录器;
类LogBackend{
公众:
LogBackend(){}
显式LogBackend(const std::string和name);
虚拟~LogBackend(){}
虚拟无效日志(常量记录器::级别l,常量标准::字符串和文本)=0;
/*
方法接口
*/
bool-valid();
std::string getName();
受保护的:
bool m_valid=true;
std::字符串m_名称;
};
}
#恩迪夫
注意:有LogBackend的派生类

Logger.h

#ifndef LOGGER_BACKEND_H
#define LOGGER_BACKEND_H

#include "Logger.h"
#include <string>

namespace se {
    class Logger;
    class LogBackend {
    public:

        LogBackend() { }
        explicit LogBackend(const std::string& name);
        virtual ~LogBackend() { }

        virtual void log(const Logger::Level l, const std::string& text) = 0;

        /*
         Method interface
        */

        bool valid();
        std::string getName();

    protected:
        bool m_valid = true;
        std::string m_name;
    };
}
#endif
#ifndef LOGGER_H
#define LOGGER_H

#include "LogBackend.h"
#include <string>
#include <sstream>
#include <vector>
#include <glew/glew.h>

namespace se {
    class LogBackend;
    class Logger {
    public:

        enum class Level { WARNING, INFO, EXCEPTION, SEVERE };
        static std::string to_string(Level l);

        static void add(const LogBackend& backend);

        /*
         Methods
        */

    private:
        static std::vector<LogBackend> m_backends;
    };
}
#endif
\ifndef记录器\u H
#定义记录器
#包括“LogBackend.h”
#包括
#包括
#包括
#包括
名称空间se{
类LogBackend;
类记录器{
公众:
枚举类级别{警告、信息、异常、严重};
静态标准::字符串到_字符串(l级);
静态void add(const LogBackend和backend);
/*
方法
*/
私人:
静态std::向量m_后端;
};
}
#恩迪夫

因为您正在使用,所以在Logger.h中,只有向前声明是不够的,除非您将其更改为
std::vector
std::vector

LogBackend也有类似的问题,您使用的是Logger::Level,它不可用,因为您只是转发声明的Logger


我建议您在Logger.h中使用一个指向LogBackend的指针来打破Logger.h中的依赖关系,因为您正在使用Logger.h中的一个前向声明是不够的,除非您将其更改为
std::vector
std::vector

LogBackend也有类似的问题,您使用的是Logger::Level,它不可用,因为您只是转发声明的Logger


我建议您只使用一个指向LogBackend的指针来打破Logger.h中的依赖关系,添加这些正向引用是自欺欺人的。根本的问题是LogBackend.h包含“Logger.h”,Logger.h包含“LogBackend.h”。include-guard防止无限递归,但这也意味着当编译器在源文件中看到
#include“Logger.h”
时,它会尝试编译“Logger.h”,其中包括“LogBackend.h”,其中包括“Logger.h”,因为include-guard是空的是你必须打破的循环,这是一个仔细思考什么需要什么的问题,这样你就可以拥有线性相关而不是循环的类,这将使您的标题可能是线性相关的,而不是循环的。

添加这些正向引用是自欺欺人的。根本的问题是LogBackend.h包含“Logger.h”,Logger.h包含“LogBackend.h”。include-guard防止无限递归,但这也意味着当编译器在源文件中看到
#include“Logger.h”
时,它会尝试编译“Logger.h”,其中包括“LogBackend.h”,其中包括“Logger.h”,因为include-guard是空的是你必须打破的循环,这是一个仔细思考什么需要什么的问题,这样你就可以拥有线性相关而不是循环的类,这将使您的标题可能是线性相关的,而不是循环的。

您知道
std::vector
不能包含
LogBackend
的子类,对吗?我可能错了,但我认为严格地说,如果您先有
,包括“foo.h”
,然后是
类foo它不是向前声明。
std::vector
,因为它是一个抽象类。您可以包含一个
std::vector
insteadOopsie。。。它应该一直都是LogBackend*。感谢您指出,您知道
std::vector
不能包含
LogBackend
的子类,对吗?我可能错了,但我认为严格来说,如果您先有
,包括“foo.h”
,然后是
类foo它不是向前声明。
std::vector
,因为它是一个抽象类。您可以包含一个
std::vector
insteadOopsie。。。它应该一直都是LogBackend*。谢谢你指出这一点,谢谢!但在我的例子中,将级别分解成单独的头文件更容易。很好,谢谢!但在我的例子中,将Level分解成一个单独的头文件更容易。谢谢,这让我开始思考。通过做一个线性结构(分解水平),我打破了这个循环。但是如果它们需要循环依赖,是否有一个技术(不需要解释,只需要一个关键字)呢?通常,您可以在同一个头中定义两个类,首先是第二个类的正向声明,然后定义第一个类,然后定义第二个类。如果这两个类的接口实际上都依赖于另一个类的内容,那么您就遇到了一个棘手的情况。谢谢,这让我思考了一下。通过做一个线性结构(分解水平),我打破了这个循环。但是如果它们需要循环依赖,是否有一个技术(不需要解释,只需要一个关键字)呢?通常,您可以在同一个头中定义两个类,首先是第二个类的正向声明,然后定义第一个类,然后定义第二个类。如果这两个类的接口实际上都依赖于另一个类的内容,那么您就遇到了一个棘手的情况。