C++ 循环依赖,即使类是前向声明的
这里有一个非常奇怪的问题,即使向前声明受影响的类也无法解决循环依赖关系 如您所见,这两个类都是前向声明的。有什么解释吗?未定义任何类的符号。这显然是一个循环依赖错误 提前感谢您的建议 LogBackend.hC++ 循环依赖,即使类是前向声明的,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
#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分解成一个单独的头文件更容易。谢谢,这让我开始思考。通过做一个线性结构(分解水平),我打破了这个循环。但是如果它们需要循环依赖,是否有一个技术(不需要解释,只需要一个关键字)呢?通常,您可以在同一个头中定义两个类,首先是第二个类的正向声明,然后定义第一个类,然后定义第二个类。如果这两个类的接口实际上都依赖于另一个类的内容,那么您就遇到了一个棘手的情况。谢谢,这让我思考了一下。通过做一个线性结构(分解水平),我打破了这个循环。但是如果它们需要循环依赖,是否有一个技术(不需要解释,只需要一个关键字)呢?通常,您可以在同一个头中定义两个类,首先是第二个类的正向声明,然后定义第一个类,然后定义第二个类。如果这两个类的接口实际上都依赖于另一个类的内容,那么您就遇到了一个棘手的情况。