C ++检查单例指针

时间:2010-06-30 07:55:42

标签: c++ qt singleton

我有一个应用程序,它有一个(Qt C ++)单例记录器类。 GetInstance()实现是:

if(m_Instance == NULL)
{
    try
    {
        m_Instance = new Logger();
    }
    catch(...){}
}
return m_Instance;

现在我在.h文件中有以下宏: “#define LOG Logger :: Instance() - > Log”

只要new()操作有效,一切都很好。确保指针设置的最佳方法是什么(我正在考虑一些try-catch块来捕获std :: bad_alloc,但我不知道如何在宏中实现它)?我已经创建了一个解决方法,它似乎有效,但并不漂亮:

“#define LOG if(Logger :: Instance())Logger :: Instance() - > Log”

另外,我想知道如果我的对象有很多getter / setter(例如setPath(),getSize()......)会怎么样?目前,我有一个宏:

“#define SET Settings :: Instance()”

并且在代码中我能够使用SET-> setPath(“abc”);或SET-> getSize();

在这种情况下,我丑陋的解决方法不起作用,因为它需要为每个方法单独的宏。有关如何改进的提示吗?

感谢您的回答。

7 个答案:

答案 0 :(得分:9)

不要使用糟糕的设计模式 - >不要遇到问题。通常,人们使用类似于

的东西
Logger& Logger::GetInstance() {
    static Logger instance; 
    return instance;
}

但单身人士模式一般都非常糟糕。改为使用应用程序实例模式。

答案 1 :(得分:3)

首先,你是否真的希望你的应用程序默默地忽略你对这些单身人士所做的一切,如果他们不能被分配?对于像记录器这样的东西,你可能想用它来报告异常消息,所以也许你不想让它也抛出。

对于这种情况,请考虑在应用程序启动时调用实例方法(例如:在主入口点),这样如果应用程序成功启动,它将始终有一个便于使用的记录器,例如

最后,我建议m_instance使用类似boost :: scoped_ptr的东西,这样你就不会泄漏内存(或者只是将logger作为静态对象存储在没有指针间接的实例方法中)。当然,现代操作系统通常会在您之后进行清理,但如果您开始进行内存分析以检查泄漏,那么您将会以这种方式获得大量误报。

对于这些宏,我认为它们是残暴的,但这只是我的意见。没有宏,你可以实现类似的效果:

void write_to_log(Logger* logger, const char* msg)
{
    if (logger)
        logger->log(msg);
}

甚至:

void write_to_log(const char* msg)
{
    Logger* logger = Logger::instance();
    if (logger)
        logger->log(msg);
}

答案 2 :(得分:2)

如果没有日志,你不会说你想做什么。

如果您希望错误传播,请不要捕获异常或抛出更具体的错误来指示缺少日志。

如果你想继续使用,要么在每次使用时都进行空检查,要么使用null object pattern用虚拟方法替换程序检查。

答案 3 :(得分:1)

如果您确定单身模式(这里似乎过度使用),那么:

struct ILogger {
    void Log(const char *message) = 0;
};

struct NullLogger : ILogger {
    void Log(const char *message) { }
};

struct Logger : ILogger {
private:
    static ILogger *m_instance;
    static const NullLogger m_null_instance;

public:
    void Log(const char *message) { /* ... */ }

    static ILogger *Instance() {
        if(m_Instance != &m_null_instance) return m_Instance;

        try { m_Instance = new Logger(); } catch(...) { }

        return m_Instance;
    }
};

const NullLogger Logger::m_null_instance;
ILogger *Logger::m_instance = &Logger::m_null_instance;

/* ... */
#define LOG Logger::Instance()->Log
LOG("Hey!");

答案 4 :(得分:0)

您已经在GetInstance方法中捕获到异常,因此无论如何都不会出现在宏中。也许...

if(m_Instance == NULL)
{
    try
    {
        m_Instance = new Logger();
    }
    catch (std::bad_alloc &ba)
    {
        // do something here...
    }
    catch(...){}
}

return m_Instance;

答案 5 :(得分:0)

(1)正如其他人所说:不要使用单身人士。 (2)如果使用单例,请使用具有可靠实现的单例。 (3)如果你想要一个HACK:

void Logger::Log( /*params*/ )
{
  if( NULL != this )
  {
    // do your logging
    ...
  }
}

答案 6 :(得分:0)

感谢您的回复。

我的单例实现基于Web中提供的各种示例创建。 (例如http://www.yolinux.com/TUTORIALS/C++Singleton.html非常接近我的。)

我使用单例的原因是为了确保只有一个类的实例(记录器/设置),是的,我知道它被过度使用。

然而,看起来我必须尝试在不使用单例的情况下实现类似的东西。