单例设计模式 - 显式声明类外的构造函数

Singleton Design Pattern - Explicitly stating a Constructor outside the class

本文关键字:构造函数 声明 设计模式 单例      更新时间:2023-10-16

我试图实现单例模式,假设只使用私有构造函数、类的私有实例和公共静态方法来返回实例。但是我在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;
}

错误为 :

LNK2019未解析的外部符号"private: __thiscall Singleton::Singleton(void)"(??0Singleton@@AAE@XZ) 在函数"public: static class Singleton * __cdecl Singleton::getInstance(void)"中引用(?getInstance@Singleton@@SAPAV1@XZ)

然后我解决了错误,但在类外重写了构造函数

Singleton::Singleton() {
}

我想知道错误的原因以及为什么需要在类外部显式编写构造函数。

在类中,构造函数只是声明的,而不是定义的。定义包括函数体。无论您是在类中内联定义它还是在类外部(就像您所做的那样)定义它并不重要,但一个小小的区别是,在类中定义它是隐式inline的。


在其他新闻中:

  • 单例通过避免静态初始化顺序惨败来改进全局变量,但在不可见的通信线路和副作用方面存在相同的问题。最好避免。

  • 如果你不需要在相应的全局变量被销毁后保留一个单例,那么只需使用一个简单的迈耶斯单例。

这是迈耶斯的单身人士:

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

默认构造函数需要一个主体:

你可以改变

Singleton();

Singleton(){};

在类内部,它应该可以工作。

使用 C++11,我们可以使用"default"说明符来指示编译器创建构造函数的默认实现。

请参阅以下对我有用的代码片段:

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;
    }
};

在Meyer单例的演变中,我更喜欢值语义单例,原因如下所述:

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());
}

帕加达拉是对的。缺少构造函数定义,因此链接器错误