Reputation: 3075
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 to
myClass::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 ...
Upvotes: 1
Views: 1041
Reputation: 24626
//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!)
Upvotes: 2
Reputation: 1729
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.
Upvotes: 1