1

I am trying to learn singleton pattern and I am faced with a design dilemma .

A working singleton looks like following: note that static myClass * mc; is made public , just like public static myClass * getInstance

1) working_code

#include "iostream"
using namespace std;

class myClass {
private:  
   myClass() {          
   }
 void   operator = (const myClass &);
 myClass (const myClass & );

public:
   static myClass * mc;
   static myClass * getInstance () {
       cout << "\n getInstance  callsed \n";
       if (mc == NULL) {
           mc = new myClass();
       }
       return mc;
    }

 void print() {
     cout <<"\n call to print donem \n";
 }

};
myClass * myClass::mc =NULL;

int main() {    
    myClass * mc = myClass::getInstance ();
    mc->print();
    return 0;
}

2) NOT_WORKING_CODE

Not working instance which gives compiler error. Please note that I tried to keep static myClass * mc; as private

#include "iostream"
using namespace std;

class myClass {
private: 
   static myClass * mc;
   myClass() {        
   }
 void   operator = (const myClass &);
 myClass (const myClass & );

public:
    static myClass * getInstance () {
        cout << "\n getInstance  callsed \n";
        if (mc == NULL) {
            mc = new myClass();
        }
        return mc;
    }

 void print() {
    cout <<"\n call to print donem \n";
 }

};

int main() {

    myClass * mc = myClass::getInstance ();
    mc->print();
    return 0;
}

output: In function main': undefined reference tomyClass::mc' undefined reference to `myClass::mc'

problem :

1) Why am I getting the error for above NOT_WORKING_CODE

2) I think using public myClass::mc is against design rule as we should be making only the interface as public . Here problem I am facing is that the users of working code 1) above may directly access myClass::mc to call some function like print myClass::mc->print(); without first calling instance ..

ie when I changed the following in 1) above

int main() {
    myClass::mc->print();
    myClass * mc = myClass::getInstance ();
    mc->print();
    return 0;
}

I got horrified as it printed

call to print donem 

 getInstance  callsed 

 call to print donem 

ie, I was able to call without a valid instance as that instance was created in getInstance . This means I could have well got some exception if print was accesing some pointers etc .

This hence shows that 1) is having a design flaw . How to correct the same is the question ...

Sanish
  • 1,699
  • 1
  • 12
  • 21
MAG
  • 2,841
  • 6
  • 27
  • 47

2 Answers2

2

//myClass * myClass::mc =NULL; The error appears because you commented that line out, not because you made the variable private. So to make the code work with the variable private, just don't comment that line out and it will compile.

See here:What is an undefined reference/unresolved external symbol error and how do I fix it?

But you should never use the singleton pattern this way. In fact, try to avoid using singletons at all, and if you really have to use them, use the Meyers Singleton (google for it!)

Community
  • 1
  • 1
Arne Mertz
  • 24,171
  • 3
  • 51
  • 90
  • i am, more concerned with my second point ie how to make this implementation more safe ... I already gave a working code as point 1) .. – MAG May 27 '13 at 06:55
  • As I said, the error has nothing to do with the variable being private. Meaning, you can fix the error and leave the variable private and relatively "save" wrt. access. It's not threadsafe though. – Arne Mertz May 27 '13 at 07:01
  • 1
    @Arne Mertz, somebody wrote a book and said "do not use singletons". And it became a religion. Singleton is perfectly ok and useful if used properly. Btw, threadsafe or not, it has nothing to do with this subject. – user1764961 May 27 '13 at 07:08
  • @user1764961 I addressed the subject in the first lines of my answer. The other lines were only further information. There is no sense in learning the static-pointer singleton if it comes to bite you when you go concurrent, and the Meyers Singleton is even less complicated, avoids thread safety issues and the issue of this thread. Wrt the religion - I did not say "religiously don't", I said "avoid". Of course there are some few cases where Singletons are ok and useful, but they are often overused and introduce unnecessary problems and coupling. – Arne Mertz May 27 '13 at 07:18
  • @ArneMertz i note that myClass * myClass::mc =NULL works evern if I make the static myClass * mc; as private .. Can you tell me why ? how are we able to acccess this private outside http://codepad.org/4vjI3y6M – MAG May 27 '13 at 07:32
  • 1
    @MAG you can (and very often have to) *define* static class members outside the class definition, regardless of their access modifiers. You can do this because it's a definition, not an access. The same goes for functions: you can define `void foo::bar() {}` in the .cpp outside the class definition, although it's private. – Arne Mertz May 27 '13 at 07:58
  • @ArneMertz thanx for closing the gap :) – MAG May 27 '13 at 08:12
1

mc is a static data member, so it has to explicitly initialized as you did in your first case.

myClass * myClass::mc =NULL;

You missed to do this in the second case.

See this link http://www.parashift.com/c++-faq/link-errs-static-data-mems.html

BTW, that is a linker error not a compiler error.

Sanish
  • 1,699
  • 1
  • 12
  • 21