Given the singleton class
class MySingleton
{
// ...
public:
MySingleTon& instance() { /* ... */ }
};
is it possible to prevent:
int main()
{
// the following should cause some error
MySingleton& singleton = MySingleton::instance();
}
while still allowing:
int main()
{
// Only directly accessing MySingleton::instance().SomeMethod should be possible
MySingleton::instance().some_method();
}
Extra example
int main()
{
// Following two lines should error
MySingleton& singleton = MySingleton::instance();
singleton.some_method();
// Following line should NOT error
// Additionally it should be the only way to access any MySingleton method besides MySingleton::instance
MySingleton::instance().some_method();
}
The only way I know to do what you are looking for is to make instance() itself be private so code that is outside of MySingleton can't call it directly, then add a static method to MySingleton that is public and uses instance() internally as needed, eg:
class MySingleton
{
// ...
private:
MySingleton() { /* ... */ }
static MySingleton& instance() { static MySingleton inst; return inst; }
public:
static void do_method() { instance().some_method(); }
};
int main()
{
MySingleton& singleton = MySingleton::instance(); // <-- ERROR
singleton.some_method();
MySingleton::do_method(); // <-- OK
}
Related
Is it possible to define a Meyer's singleton (like this one) with arguments?
I know it is possible with the GOF style singleton (like here),
but I can't seem to make it work with Meyer's singletons:
// ...
public:
static S& getInstance()
{
static S instance; // no way to pass arguments here ...
return instance;
}
EDIT:
I want a single Init function, and multiple getInstance.
So a typical usage is something like:
S::Init(5, 6.4);
foo(S::getInstance());
bar(S::getInstance());
You can just store the initialization parameters in statics. Example:
class S {
public:
static void Init(int i)
{
i_ = i;
initialized_ = true;
}
static S& getInstance()
{
if (!initialized_) {
throw SomeException;
}
static S instance(i_);
return instance;
}
private:
S(int) { }
static int i_;
static bool initialized_;
};
Remember to actually define the statics in the implementation (.cpp) file:
int S::i_ = 0;
bool S::initialized_ = false;
Obviously you could use Meyer singletons as well for these, but since they're built-in types and do not depend on other data, you wouldn't really gain much.
You could do something like this:
class Singleton
{
private:
static std::unique_ptr<Singleton>& getObject()
{
static std::unique_ptr<Singleton> instance;
return instance;
}
Singleton(int foo);
public:
static void Init(int foo)
{
auto& instance = getObject();
if (instance) throw std::runtime_error("aleady inited");
instance.reset(new Singleton(foo));
}
static Singleton& getInstance()
{
auto& instance = getObject();
if (!instance) throw std::runtime_error("not inited");
return *instance;
}
};
Note that this isn't thread safe and will have undefined behaviour if multiple threads call Init or a thread calls getInstance whilst another is calling Init.
If your parameters could be replaced by template arguments then you could do it this way instead:
template <int foo>
class SingletonImpl
{
private:
SingletonImpl(int f);
public:
static SingletonImpl<foo>& getInstance()
{
static SingletonImpl<foo> instance(foo);
return instance;
}
};
using Singleton = SingletonImpl<10>;
The best solution is probably to separate initialisation and construction:
class Singleton
{
private:
std::atomic<bool> initialised;
Singleton()
: initialised(false)
{
}
Singleton& instanceImpl()
{
static Singleton singleton;
return singleton;
}
public:
void Init(int foo)
{
auto& instance = instanceImpl();
if (instance.initialised) throw std::runtime_error("already inited");
instance.initialised = true;
}
Singleton& getInstance()
{
auto& instance = instanceImpl();
if (!instance.initialised) throw std::runtime_error("not inited");
return instance;
}
};
I'm new to programing and I was trying for the program which makes the class singleton..Is this the correct approach for making a class singleton??
#include <iostream>
using namespace std;
class Singleton
{
private:
static bool instanceFlag;
static Singleton *single;
public:
static Singleton* getInstance();
void method();
~Singleton()
{
instanceFlag = false;
}
};
bool Singleton::instanceFlag = false;
Singleton* Singleton::single = NULL;
Singleton* Singleton::getInstance()
{
if(! instanceFlag)
{
single = new Singleton();
instanceFlag = true;
return single;
}
else
{
return single;
}
}
void Singleton::method()
{
cout << "Method of the singleton class";
}
int main()
{
Singleton *sc1,*sc2;
sc1 = Singleton::getInstance();
sc1->method();
sc2=Singleton::getInstance();
sc2->method();
return 0;
}
Is this the correct way of making class singleton??
You are over-complicating things. Try the Scott Meyers singleton:
struct SingletonClass {
// instance() function return a reference
static SingletonClass& instance() {
// static local variable are initialized one time.
static SingletonClass inst;
// We return the instance, which is the same for every calls.
return inst;
}
private:
// Private since we don't want other class to create instances
SingletonClass() = default;
// Our class is not copiable or movable
SingletonClass(const SingletonClass&) = delete;
SingletonClass(SingletonClass&&) = delete;
SingletonClass& operator=(const SingletonClass&) = delete;
SingletonClass& operator=(SingletonClass&&) = delete;
};
You can use your class like that:
auto& myInstance = SingletonClass::instance();
Bonus: It doesn't use dynamic allocation, it's thread safe, and is much simpler.
try this solution:
class Singleton {
private:
static Singleton* instance;
Singleton() {} // must be private
public:
static Singleton* getInstance() {
if (instance == NULL)
instance = new Singleton();
return instance;
}
void method() { cout << "Method of the singleton class\n"; }
};
Singleton* Singleton::instance = NULL;
I see errors like
src/singleton.cxx:16:error: invalid use of member 'Singleton::instance' in static member function
src/singleton.cxx:28:error: from this location
src/singleton.cxx:16:error: invalid use of member 'Singleton::instance' in static member function
src/singleton.cxx:29:error: from this location
src/singleton.cxx:16:error: invalid use of member 'Singleton::instance' in static member function
src/singleton.cxx:31:error: from this location
src/singleton.cxx: In function 'int main()':
Now after making changes I get the following errors
singleton-rhel6.3.o: In function Singleton::get_instance()':
src/singleton.cxx:27: undefined reference toSingleton::instance'
#include <cstddef>
class Singleton {
private:
Singleton();
static Singleton * instance;
int m_num;
int incr_call();
public :
static Singleton * get_instance();
};
Singleton * Singleton::get_instance() {
if(instance == NULL)
instance = new Singleton();
return instance;
}
Singleton::Singleton():
m_num(0)
{
}
int Singleton::incr_call() {
return m_num++;
}
int main() {
Singleton * s = Singleton::get_instance();
return 0;
}
instance should be static since you want to be able to call it in get_instance. Also, instance should be private:
class Singleton {
public :
static Singleton * get_instance();
private:
Singleton();
static Singleton * instance;
int m_num;
int incr_call();
};
Singleton* Singleton::instance;
You should change your constructor too, to not initialize instance:
Singleton::Singleton():
m_num(0)
{ }
Because instance is static default initialization is done and it will be NULL / nullptr.
If you have to use singleton, use Meyers' one:
class Singleton {
private:
Singleton() = default;
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
public :
static Singleton& get_instance()
{
static Singleton instance;
return instance;
}
// Extra stuff
};
I have implemented Singleton class method hpp and cpp like the following
Singleton.hpp
class Singleton {
private:
Singleton();
public:
virtual ~Singleton();
static Singleton &instance();
int getMemberField();
void setMemberField(int mf);
private:
static Singleton *p_instance;
int m_memberField;
};
Singleton.cpp
Singleton* Singleton::p_instance=NULL ;
Singleton::Singleton() {
p_instance = this;
m_memberField = 0;
}
Singleton::~Singleton() {
p_instance = NULL;
}
Singleton& Singleton::instance() {
if (p_instance==NULL) {
p_instance = new Singleton();
}
return *p_instance;
}
int Singleton::getMemberField(){
return m_memberField;
}
void Singleton::setMemberField(int mf){
m_memberField = mf;
}
My problem is how to access those methods either set or get in application classes.
Please help,
Singleton::instance().setMemberField(42);
Whats the correct way of implementing this class?
//Header
#include <boost/shared_ptr.hh>
class MyClass
{
public:
static foo()
static foobar();
private:
class pimpl;
static boost::shared_ptr<pimpl> m_handle;
static bool initialized;
};
//source
namespace
{
bool init()
{
//...
// init() can't access m_handle, unless it is a friend of MyClass
// but that seems a bit "tacky", is there a better way?
}
}
class MyClass::pimpl
{
public:
~pimpl(){}
}
bool MyClass::initialized = init();
MyClass::foo()
{
//...
}
MyClass::foobar()
{
//...
}
MyClass is a singleton -- some call it a glorified global. An oft-abused pattern. Use private ctors and a public static accessor:
MyClass {
public:
static MyClass& Instance() {
static MyClass obj;
return obj;
}
// ...
private:
MyClass() : m_handle(pimpl()), initialized(true) {}
// ...
};