1

我有一个带有一些单例对象的应用程序。他们希望在构造和销毁时写入日志消息,这发生在全局变量的初始化时。现在日志记录提供程序也是一个像这样的单例对象:

// loggingProvider.h
class LoggingProvider {
    static boost::shared_ptr<LoggingProvider> instance;
public:
    static boost::shared_ptr<LoggingProvider> getInstance();
    /* ... */
};

// loggingProvider.cpp
boost::shared_ptr<LoggingProvider> LoggingProvider::instance;

boost::shared_ptr<LoggingProvider> getInstance() {
    if (!instance) {
        instance.reset(new LoggingProvider());
    }
    return instance;
}

记录器界面如下所示:

// logger.h
class Logger {
    const boost::shared_ptr<LoggingProvider> provider;
    const std::string prefix;
public:
    Logger(const std::string prefix);
    /* ... */
}

// logger.cpp
Logger::Logger(const std::string& prefix) :
        provider(LoggingProvider::getInstance()), prefix(prefix) {}

这个想法是能够在多个 cpp 文件中将记录器声明为全局变量,并确保在所有记录器被销毁记录日志提供程序也被销毁,因为它是由boost::shared_ptr. 如果我在文件顶部声明这样的记录器,则可以保证在同一文件中的任何单例对象之后将其破坏:

// somewhere.cpp
static Logger logger("Somewhere");

可悲的是,这段代码不起作用。当我调试它时,实例LoggingProvider被创建了多次。我相信是这种情况,因为该instance字段实际上是在一些记录器声明之后初始化的。现在我知道没有办法跨文件控制全局变量的初始化,那么还有另一种方法可以让它工作吗?

4

1 回答 1

1

只需使用经典的单例习语。你不想 shared_ptr在这里,因为你永远不想破坏对象。基本上,类似:

class LoggingProvider
{
    static LoggingProvider* our_instance;
public:
    static LoggingProvider& instance();
    //  ...
};

LoggingProvider* LoggingProvider::our_instance
        = &LoggingProvider::instance();

LoggingProvider&
LoggingProvider::instance()
{
    if ( our_instance == NULL ) {
        our_instance = new LoggingProvider;
    }
    return *our_instance;
}

这里重要的是 1) 指针没有重要的构造函数,以及 2) 实例永远不会被破坏。

一件事:由于您要输出的任何文件都永远不会关闭,因此请确保刷新所有输出。(我通常通过使用实际记录器的短期临时实例来做到这一点,它从 获取目标流缓冲区LoggerProvider,并将其刷新到它们的析构函数中。)

于 2013-07-01T13:23:34.620 回答