本文首发于个人博客https://kezunlin.me/post/8932eaec/,欢迎阅读!
singleton class and usage in c++.
Guide
what singleton solve?
Singletons solve one (and only one) problem.
Resource Contention.
If you have some resource that(1) can only have a single instance, and
(2) you need to manage that single instance,
you need a singleton.
There aren't many examples. A log file is the big one. You don't want to just abandon a single log file. You want to flush, sync and close it properly. This is an example of a single shared resource that has to be managed.
It's rare that you need a singleton. The reason they're bad is that they feel like a global and they're a fully paid up member of the GoF Design Patterns book.
When you think you need a global, you're probably making a terrible design mistake.
local static object
Actually, in C++ preferred way is local static object.
singleton pure
class Singleton { private: Singleton(); public: Singleton(Singleton const&) = delete; Singleton& operator=(Singleton const&) = delete; static Singleton& instance() { static Singleton INSTANCE; return INSTANCE; } };
singleton with shared_ptr
class Singleton { private: Singleton(); public: Singleton(Singleton const&) = delete; Singleton& operator=(Singleton const&) = delete; static std::shared_ptr<Singleton> instance() { static std::shared_ptr<Singleton> s{new Singleton}; return s; } };
singleton usage
#define DISALLOW_COPY(TypeName) \ TypeName(const TypeName&) #define DISALLOW_ASSIGN(TypeName) \ TypeName& operator=(const TypeName&) #define DISALLOW_COPY_AND_ASSIGN(TypeName) \ TypeName(const TypeName&); \ TypeName& operator=(const TypeName&) class CSingleton { public: static CSingleton &GetInstance() { static CSingleton instance; return instance; } void DoSomething() { printf("void CSingleton::DoSomething() called.\n"); } private: CSingleton() {}; DISALLOW_COPY_AND_ASSIGN(CSingleton); }; // usage CSingleton::GetInstance().DoSomething(); // OK CSingleton& singleton = CSingleton::GetInstance(); // OK with reference singleton.DoSomething(); CSingleton singleton = CSingleton::GetInstance(); // ERROR (copy constructor)
Example
config.h
#pragma once class Config { public: static Config& GetInstance(std::string filename="./config.ini"); ~Config(); private: Config(std::string filename); Config(const Config& ref) {} Config& operator =(const Config& ref) { return *this; } };
config.cpp
#include "Config.h" /* static config instance will only be created once by calling Config::Config, when program exit,static variable will be destoryed by calling Config::~Config. */ Config& Config::GetInstance(std::string filename) { static Config instance(filename); return instance; } Config::Config(std::string filename) { std::cout << "[LOG] Config::Config count= "<<count << std::endl; // load config from filename // ... } Config::~Config() { std::cout << "[LOG] Config::~Config count= " << count << std::endl; }
mysqldb.cpp
void MysqlDb::load_config(std::string filename) { this->mysql_connection = Config::GetInstance(filename).MYSQL_CONNECTION; this->mysql_username = Config::GetInstance(filename).MYSQL_USERNAME; this->mysql_password = Config::GetInstance(filename).MYSQL_PASSWORD; this->mysql_database = Config::GetInstance(filename).MYSQL_DATABASE; this->max_connection_pool_size = Config::GetInstance(filename).MAX_CONNECTION_POOL_SIZE; }
Reference
History
- 20180122: created.
Copyright
- Post author: kezunlin
- Post link: https://kezunlin.me/post/8932eaec/
- Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.