c ++单例类实例访问所有应用程序

时间:2015-04-11 11:39:57

标签: c++

我试图用c ++中的threadsafe实践编写一个日志类。现在问题是,我希望对每个日志行的调用非常简单。我可以使用下面的静态类方式:

//Calling this in some GUI initialization point of application
CLogger::InitLogger("LogFile.log");

//Calling below from any class just adding the header to the cpp
CLogger::Log("Some informational text goes here");

现在这并不遵循OOP,所以想要使用单例类。

//Singleton log class
class CLogWrite
{
public:
  static CLogWrite* GetInstance();

private:
  static CLogWrite *pInstance;
  void Log();
};

CLogWrite* CLogWrite::GetInstance()
{
  if(pInstance != NULL)
  {
    pInstance = new CLogWrite;
  }
  return pInstance;
}

void CLogWrite::Log()
{
  //threadSafe lock

  //write 'logText' to file here

  //threadSafe unlock
}

现在问题是,如果我在类上面编写并在我的GUI类init函数中调用CLogWriter :: GetInstance(),如下所示:

//single logger instance for my app
CLogWriter *mLogInstance;
mLogInstance = CLogWriter::GetInstance()

我需要通过' mLogInstance'变量到我想要编写日志的项目中的每个类。但我不想那样做。

什么是最好的方法?

2 个答案:

答案 0 :(得分:2)

试试这个:

class Singleton
{
public:
    static Singleton& getInstance()
    {
        static Singleton instance;
        return instance;
    }

    Singleton(Singleton const&) = delete;
    void operator=(Singleton const&) = delete;

private:
    Singleton() {};        
};

答案 1 :(得分:1)

我最喜欢的C ++技术之一就是所谓的CRTP,它可以用来实现单例逻辑。看看这段代码:

template <class Type>
class Singleton
{
private:
    static std::unique_ptr<Type>    _holder_ptr;
    static std::mutex               _mutex;

public:
    static Type& GetSingleton()
    {
        if(!_holder_ptr)
            _create_instance();

        return *(_holder_ptr.get());
    }

protected:
    static void _create_instance()
    {
        _mutex.lock();

        if(!_holder_ptr)
            _holder_ptr.reset(new Type());

        _mutex.unlock();
    }
};

现在,您可以使用此类来定义&#34;单身&#34;:

class Log : public Singleton<Log>
{
    //content
};

并使用它:

Log& global_log = Log::GetSingleton();
//do something

这是C ++ 11的版本。对于较旧的编译器,请将std::mutex替换为与平台相关的同步原语。在Windows上,您可能希望使用CRITICAL_SECTION。示例用法:here

std::unique_ptr也在C ++ 11中引入,因此您可以将其替换为std::auto_ptr(在C ++ 11中弃用),使用smart pointer from Boost library或创建自己的解决方案(这并不困难) ,但重新发明轮子不是一个好主意。)

请注意,此Singleton并不禁止创建Log的其他实例 - 而且它不应该!有两种常见的情况:

  • 您允许用户创建Log的其他实例,但同时要求,必须至少存在一个此类对象。然后,简单派生自Singleton就是你所需要的。
  • 您需要Log为真&#34; Singleton&#34;,即:只有一个共享实例可以存在 - 其余代码必须使用此实例,因此一切都可以按预期工作。在这种情况下,使用= delete语法删除默认构造函数,复制构造函数和赋值运算符(或简单地将它们声明为protectedprivate,具体取决于编译器对= delete语法的支持)。

另外,请记住,如果您想将共享实例作为指针,您需要使用某种智能指针,如上所示。您不能像在原始解决方案中那样使用普通指针:

CLogWrite* CLogWrite::GetInstance()
{
    if(pInstance != NULL)
    {
        pInstance = new CLogWrite;
    }
    return pInstance;
}

pInstance何时何地被销毁?怎么样?