0
votes

I was trying to implement singleton pattern with an assumption of just using a private constructor, private instance of the class and a public static method to return the instance. But I encountered an error to the following code in Visual Studio

// Singleton Invoice
#include <iostream>
using namespace std;

class Singleton {
public:
  //Public Static method with return type of Class to access that instance.
  static Singleton* getInstance();
private:
  //Private Constructor
  Singleton();
  //Private Static Instance of Class
  static Singleton* objSingleton;
};

Singleton* Singleton::objSingleton = NULL;

Singleton* Singleton::getInstance() {
  if (objSingleton == NULL) {
    //Lazy Instantiation: if the instance is not needed it will never be created
    objSingleton = new Singleton();
    cout << "Object is created" << endl;
  }
  else
  {
    cout << "Object is already created" << endl;
  }
  return objSingleton;
}

int main() {
  Singleton::getInstance();
  Singleton::getInstance();
  Singleton::getInstance();
  return 0;
}

The error as :

LNK2019 unresolved external symbol "private: __thiscall Singleton::Singleton(void)" (??0Singleton@@AAE@XZ) referenced in function "public: static class Singleton * __cdecl Singleton::getInstance(void)" (?getInstance@Singleton@@SAPAV1@XZ)

Then I resolved the error but rewriting the constructor outside the class

Singleton::Singleton() {
}

I would like to know the cause for the error and why a constructor needs to be explicitly written outside the class.

5
I think its because you declared the constuctor but didn't implement it. BTW are you a Fanshawe College student by chance? Just curiouskburlz
You're creating pointers to your getInstance method and singleton object. Have you tried dereferencing in main?almostcolin
@kburlz I am a student at University of Bridgeport :D , This was an example my professor found on internet to teach us Singleton pattern so when I was writing it on my own, I encountered the problem and was curious about it. I guess you might have been taught through the same example :DxAditya3393
@almostcolin When I first saw the error I got was thinking maybe the compiler wasn't able to distinguish static object and the get method, so when I looked back to the lecture slides, I noticed the constructor being explicitly specifiedxAditya3393

5 Answers

3
votes

The default constructor needs a body:

You could change

Singleton();

to

Singleton(){};

inside the class and it should work.

3
votes

In the class the constructor was only declared, not defined. A definition includes a function body. It doesn't matter much whether you define it inline in the class, or outside the class (as you did), but one little difference is that with a definition in the class it's implicitly inline.


In other news:

  • Singletons improve on global variables by avoiding e.g. the static initialization order fiasco, but have the same problems with respect to invisible lines of communication and side effects. Best avoided.

  • If you don't need a singleton to persist after a corresponding global variable would be destroyed, then just use a simple Meyers' singleton.

Here's a Meyers' singleton:

class Foo
{
private:
    Foo() {}
public:
    static auto instance()
        -> Foo&
    {
        static Foo the_instance;
        return the_instance;
    }
};
1
votes

With C++11 we can use the 'default' specifier to instruct the compiler to create the default implementation of the constructor.

Refer to the below code snippet which is working for me:

class Singleton
{
    static Singleton* m_instance;
    Singleton()=default;   /* Note the use of default specifier here*/
public:
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
    static Singleton* getInstance()
    {
        if(!m_instance){m_instance= new Singleton();}
        return m_instance;
    }
};
0
votes

In an evolution of the Meyer's singleton, I prefer the value-semantic singleton, for reasons mentioned in the code below:

class singleton
{
  // private implementation
  struct impl {
    void do_something() { }
  };

  // private decision as to whether it's really a singleton and what its lifetime
  // will be
  static impl& instance() { static impl _impl; return _impl; }

public:
  // public interface defers to private lifetime policy and implementation
  void do_something() { instance().do_something(); }
};

void something(singleton s)
{
  s.do_something();
}

int main()
{
  // we can now pass singletons by value which gives many benefits:
  // 1) if they later become non-singletons, the code does not have to change
  // 2) the implementation can be private so better encapsulation
  // 3) we can use them in ADL more effectively
  auto x = singleton();
  something(x);
  something(singleton());
}
0
votes

Pagadala is right. The constructor definition is missing hence the linker error