cpp中的构造函数无限循环
Constructors infinite cycle in cpp
我有一个 Logger
单例 class 其目的是将消息打印到日志文件/屏幕。
这个 Logger 有一些他想从配置文件中读取的配置。这是 Logger 的构造函数:
Logger::Logger(const std::string& confFilePath) {
m_logConf = new LogConfig(confFilePath);
...
}
Class LogConfig
使用知道如何解析配置文件的配置对象。这里是 class Ctor
:
LogConfig::LogConfig(const std::string& confFilePath) {
m_config = new Configuration(confFilePath);
...
m_config->ParseConfFile();
}
问题是在 ParseConfFile
方法中 - 配置对象可能想要写入日志并使用 Logger 单例 class。但是,当它尝试这样做时 - 他将再次进入 Logger 构造函数,然后进入 LogConfig Ctor 并且存在无限循环。
我不想禁止配置 class 写入日志(LogConfig
不是唯一使用它的 class)。
如何解决这个循环问题?
用最低限度初始化记录器,这样您根本不需要配置。
然后当你有配置时替换记录器。
如果配置 reader 需要记录任何内容,它将转到最低限度的记录器,因此您至少应该将其转储到 stderr。
此外,如果您在 multi-threaded 环境中,请确保您使用 shared_ptr 并进行原子交换以将其替换为合适的(以防其他模块在您需要时记录日志)交换)。
由于Logger
是一个单例,假设所有类(包括Configuration
)都通过静态方法(比如getInctance()
)访问它,而Logger
的构造函数是私有的。正确的方法是将 Logger 的构造简化到最低限度,并将 setup/configuration 逻辑从构造函数移至 getInstance()
.
类似于:
static Logger* Logger::getInstance() {
if (m_logger == nullptr) {
m_logger = new Logger(); // remove configuration path passing from the constructor
m_logger->setConfigPath(const std::string& confFilePath); // ok trying to write to Logger, at least from the perspective of not being stuck in construction loop
}
return m_logger;
}
虽然这种情况下的行为仍然需要定义,因为当配置尝试写入时记录器没有完全初始化。
一种方法是在完全初始化之前有人想使用 Logger
时抛出异常或将错误消息写入标准输出。
我有一个 Logger
单例 class 其目的是将消息打印到日志文件/屏幕。
这个 Logger 有一些他想从配置文件中读取的配置。这是 Logger 的构造函数:
Logger::Logger(const std::string& confFilePath) {
m_logConf = new LogConfig(confFilePath);
...
}
Class LogConfig
使用知道如何解析配置文件的配置对象。这里是 class Ctor
:
LogConfig::LogConfig(const std::string& confFilePath) {
m_config = new Configuration(confFilePath);
...
m_config->ParseConfFile();
}
问题是在 ParseConfFile
方法中 - 配置对象可能想要写入日志并使用 Logger 单例 class。但是,当它尝试这样做时 - 他将再次进入 Logger 构造函数,然后进入 LogConfig Ctor 并且存在无限循环。
我不想禁止配置 class 写入日志(LogConfig
不是唯一使用它的 class)。
如何解决这个循环问题?
用最低限度初始化记录器,这样您根本不需要配置。 然后当你有配置时替换记录器。
如果配置 reader 需要记录任何内容,它将转到最低限度的记录器,因此您至少应该将其转储到 stderr。
此外,如果您在 multi-threaded 环境中,请确保您使用 shared_ptr 并进行原子交换以将其替换为合适的(以防其他模块在您需要时记录日志)交换)。
由于Logger
是一个单例,假设所有类(包括Configuration
)都通过静态方法(比如getInctance()
)访问它,而Logger
的构造函数是私有的。正确的方法是将 Logger 的构造简化到最低限度,并将 setup/configuration 逻辑从构造函数移至 getInstance()
.
类似于:
static Logger* Logger::getInstance() {
if (m_logger == nullptr) {
m_logger = new Logger(); // remove configuration path passing from the constructor
m_logger->setConfigPath(const std::string& confFilePath); // ok trying to write to Logger, at least from the perspective of not being stuck in construction loop
}
return m_logger;
}
虽然这种情况下的行为仍然需要定义,因为当配置尝试写入时记录器没有完全初始化。
一种方法是在完全初始化之前有人想使用 Logger
时抛出异常或将错误消息写入标准输出。