我有一个Logger
单件类,其目的是将消息打印到日志文件/屏幕。
此Logger具有一些他想要从配置文件中读取的配置。这是Logger的构造函数:
Logger::Logger(const std::string& confFilePath) {
m_logConf = new LogConfig(confFilePath);
...
}
类LogConfig
使用知道如何解析配置文件的配置对象。这是课程Ctor
:
LogConfig::LogConfig(const std::string& confFilePath) {
m_config = new Configuration(confFilePath);
...
m_config->ParseConfFile();
}
问题是在ParseConfFile
方法中 - 配置对象可能想要写入日志并使用Logger单例类。但是,当它试图这样做时 - 他将再次进入Logger构造函数,然后再进入LogConfig Ctor并且存在无限循环。
我不想禁止Configuration类写入日志(LogConfig
不是唯一使用它的类。)
如何解决这个循环问题?
答案 0 :(得分:3)
将记录器初始化为最低限度,因此您根本不需要配置。 然后,当您有配置替换记录器。
如果配置阅读器需要记录任何内容,它将转到最小的记录器,因此您至少应将其转储到stderr。
此外,如果您处于多线程环境中,请确保使用shared_ptr并执行原子交换以将其替换为propper(如果需要交换时某些其他模块正在记录)。
答案 1 :(得分:2)
由于Logger
是一个单例,假设所有类(包括Configuration
)都通过静态方法(比如getInctance()
)访问它,而Logger
的构造函数是私有的。正确的方法是将Logger的构造简化为最小化,并将设置/配置逻辑从构造函数移动到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
完全初始化之前使用public class ViewModel: INotifyPropertyChanged
{
public ObservableCollection<Item> Items { get; set; }
...
}
public class Item: INotifyPropertyChanged
{
public SubItem A { get; set; }
public SubItem B { get; set; }
...
}
public class SubItem: INotifyPropertyChanged
{
public bool Valid { get; set; }
...
}
时,一种方法是抛出异常或将错误消息写入标准输出。