构造函数在cpp中无限循环

时间:2018-02-22 12:35:46

标签: c++ constructor cycle

我有一个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不是唯一使用它的类。)

如何解决这个循环问题?

2 个答案:

答案 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; } ... } 时,一种方法是抛出异常或将错误消息写入标准输出。