0

I have a singleton A which I am going to use throughout class B, so it does not make that much sense do A::getInstance() in multiple methods rather than trying to store a reference A& ref_ to this singleton and then just call the methods of ref_. The problem is: how do I get and store A& ref_, when all constructors, copy constructors, copy assignment operators are private? How would I solve this?

--Daniel.

Daniel
  • 179
  • 2
  • 9
  • 3
    Initialise it with the result of `A::getInstance()`? Or am I missing something? – Mike Seymour Jun 02 '14 at 07:18
  • You should refer to [C++ Singleton design pattern](http://stackoverflow.com/questions/1008019/c-singleton-design-pattern) maybe ? – Karalix Jun 02 '14 at 07:22
  • @MikeSeymour I want to avoid C++11, if I am interpreting this message right "warning: non-static data member initializers only available with -std=c++11 or -std=gnu++11 [enabled by default]" – Daniel Jun 02 '14 at 07:22
  • @πάνταῥεῖ I think you might be right. Reading the question right now – Daniel Jun 02 '14 at 07:23
  • @Daniel: Initialise it in the constructor's initialiser list, e.g. `B() : ref_(A::getInstance()) {}`, if you can't use new-style initialisation. – Mike Seymour Jun 02 '14 at 07:25

1 Answers1

4

The problem is: how do I get and store A& ref_, when all constructors, copy constructors, copy assignment operators are private?

Consider this:

class A { // singleton
    A(); // private
public:
    static A& GetInstance() { // public singleton instance accessor
        static A instance; // initialized on first call to GetInstance
        return instance;
    }
};

class B {
     A& ref;
public:
    B(): ref( A::GetInstance() ) {} // ref now points to the singleton instance
};

That said, please try not to use singletons in your code. Singleton is a design pattern that increases module interdependency, makes code more monolythic and more difficult to test.

A better solution probably looks like this:

class A { // NOT a singleton
public:
    A(); // public
};

class B {
     A& ref;
public:
    B(A& aref): ref( aref ) {} // ref now points to the injected instance
                               // but doesn't impose that A::GetInstance
                               // exists (aref is dependency-injected)
};

client code:

A& a = [local object or anything else];
B b(a); // now you can inject any A instance and have no imposition
        // in B's implementation that A must be a singleton.
utnapistim
  • 26,809
  • 3
  • 46
  • 82
  • Singletons really should be considered an anti-pattern, there is always a better way. – sam Jun 02 '14 at 07:28
  • That's the answer I was looking for, and the question should be marked as duplicate as mentioned in the comments. The problem is I am trying to inject some OpenCL code into a mammoth of a software developed over the past 6+ years with some level of decoupling to the already-existing code. – Daniel Jun 02 '14 at 07:31
  • The case where the singleton instance changes is not covered by the non-singleton solution provided. It is howevere covered by a solution where no reference to the singleton is saved but a call to A::GetInstance is done whenever it is used. When saving the reference it can get tricky to know when your reference has been made unvalid. – Martin G Jun 02 '14 at 07:51
  • @scy7he, a singleton instance is "the instance" of the object, by definition (i.e. it doesn't change and doesn't become non-valid). For a non-singleton reference to A (my proposed implementation) you will have to make sure the refered-to object, has a longer lifetime than the holder of the reference. – utnapistim Jun 02 '14 at 07:55
  • @utnapistim, I don't think the singleton, "by definition" is guaranteed to stay in the same memory address until end of program execution. Of course, this is how it is in the classic implementation, but there are far more complex singletons out there which i think should still be called singletons. Regardless, I prefer your non-singleton solution as well, when applicable. – Martin G Jun 02 '14 at 08:12