关于c ++:Singleton设计模式 – 明确说明类外的构造函数

Singleton Design Pattern - Explicitly stating a Constructor outside the class

我试图实现单例模式,假设只使用私有构造函数、类的私有实例和公共静态方法返回实例。但是我在Visual Studio中遇到了以下代码的错误

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
// 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:ouu thiscall singleton::singleton(void)"(?"public:static class singleton*uu cdecl singleton::getInstance(void)"(函数"public:static class singleton*u cdecl singleton::getInstance(void)"中引用的?0singleton@@aae@xz)(?getInstance@singleton@@sapav1@xz)

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

1
2
Singleton::Singleton() {
}

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


在类中,只声明了构造函数,没有定义。定义包括函数体。不管您是在类中内联定义它,还是在类外部(如您所做的)定义它都无关紧要,但有一点不同的是,对于类中的定义,它是隐式的inline

其他新闻:

  • 单子函数通过避免静态初始化顺序的错误来改进全局变量,但是在不可见的通信线路和副作用方面也有相同的问题。最好避免。

  • 如果在相应的全局变量被销毁后不需要单例来持久化,那么只需使用简单的Meyers'singleton。

这是梅耶斯的单曲:

1
2
3
4
5
6
7
8
9
10
11
12
class Foo
{
private:
    Foo() {}
public:
    static auto instance()
        -> Foo&
    {
        static Foo the_instance;
        return the_instance;
    }
};


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

你可以改变

1
Singleton();

1
Singleton(){};

在课堂上,它应该是有效的。


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


在迈耶单例的发展过程中,我更喜欢值语义单例,原因如下代码所述:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
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());
}