代码之家  ›  专栏  ›  技术社区  ›  binyamina

cpp中的构造函数无限循环

  •  1
  • binyamina  · 技术社区  · 7 年前

    我有一个 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 singleton类。但是,当它尝试这样做时,他将再次进入Logger构造函数,然后进入LogConfig Ctor,这是一个无限循环。

    我不想禁止Configuration类写入日志( 日志配置 不是唯一使用它的类)。

    如何解决此循环问题?

    2 回复  |  直到 7 年前
        1
  •  3
  •   Sorin    7 年前

    用最小值初始化记录器,这样就根本不需要配置。 然后,在配置完成后,更换记录器。

    如果配置读取器需要记录任何内容,它将转到最小日志记录器,因此您至少应该将其转储到stderr。

    此外,如果您处于多线程环境中,请确保使用shared\u ptr并进行原子交换,以使用propper替换它(以防需要交换时其他模块正在记录日志)。

        2
  •  2
  •   nVxx    7 年前

    自从 Logger 是一个独生子女,假定所有类(包括 Configuration )通过静态方法访问它(例如 getInctance() ),和 记录器 的构造函数是私有的。正确的方法是将记录器的构造简化到最低限度,并将设置/配置逻辑从构造函数移动到 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;
    }
    

    尽管这种情况下的行为仍然需要定义,因为在配置尝试写入日志时,日志程序没有完全初始化。

    一种方法是在有人想要使用时抛出异常或向标准输出写入错误消息 记录器 在完全初始化之前。