【问题标题】:Singleton Design Pattern - Explicitly stating a Constructor outside the class单例设计模式 - 在类外显式声明构造函数
【发布时间】:2016-08-15 12:53:12
【问题描述】:

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

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

【问题讨论】:

  • 我认为这是因为您声明了构造函数但没有实现它。顺便说一句,你是范莎学院的学生吗?只是好奇
  • 您正在创建指向您的 getInstance 方法和单例对象的指针。您是否尝试过在 main 中取消引用?
  • @kburlz 我是布里奇波特大学的学生 :D ,这是我的教授在互联网上找到的一个例子来教我们单例模式,所以当我自己编写它时,我遇到了问题并且很好奇。我想您可能已经通过相同的示例进行了教学:D
  • @almostcolin 当我第一次看到错误时,我在想编译器可能无法区分静态对象和 get 方法,所以当我回顾讲座幻灯片时,我注意到了构造函数明确指定

标签: c++ design-patterns


【解决方案1】:

在类中只声明了构造函数,没有定义。定义包括函数体。是在类中内联定义它还是在类外定义它并不重要(就像你所做的那样),但有一点区别是,在类中定义它隐式为 inline


在其他新闻中:

  • 单例通过避免例如静态初始化顺序惨败,但在隐形通信线路和副作用方面存在相同的问题。最好避免。

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

这是 Meyers 的单身人士:

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

【讨论】:

  • 那么,我是否正确地假设静态变量 Foo 仅在调用函数时创建?与创建静态变量并在从不使用变量时引入低效率的普通单例不同?
  • @PagadalaVikramaditya:是的,没错。它是在第一次执行通过声明时创建的,这是第一次调用instance。在 C++11 及更高版本中,这甚至是线程安全的。
【解决方案2】:

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

你可以改变

Singleton();

Singleton(){};

在类中,它应该可以工作。

【讨论】:

    【解决方案3】:

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

    请参阅下面对我有用的代码 sn-p:

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

    【讨论】:

      【解决方案4】:

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

      【讨论】:

        【解决方案5】:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-12-28
          • 2018-06-11
          • 2014-10-12
          • 1970-01-01
          • 1970-01-01
          • 2016-04-25
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多