静态类成员在动态库中与主应用程序不同

Static class member are different within dynamic libraries from main application

本文关键字:应用程序 成员 动态 静态类      更新时间:2023-10-16

我目前正在开发一个大量使用单例和动态库(使用dlopen)的应用程序。
我的问题是我的单例在应用程序和动态库中的实例是不同的(即在我的实现中,单例::getInstance方法返回不同的地址)

这就是我定义单例的方式

// Singleton.hpp
template<typename T>
class                   Singleton
{
  static T              *_instance;
protected:
  Singleton<T>() {}
  virtual ~Singleton<T>() {}
public:
  static T              *getInstance() {
    if (_instance == NULL)
      _instance = new T;
    return (_instance);
  }
  static void           deleteInstance() {
    if (_instance) {
      delete _instance;
      _instance = NULL;
    }
  }
};
template<typename T>
T                       *Singleton<T>::_instance = NULL;

然后,如果我希望类测试是单例,我需要做:

// Test.hh
#include                   "Singleton.hpp"
class                      Test : public Singleton<Test>
{
  friend class             Singleton<Test>;
private:
  Test();
public:
  virtual ~Test();
  void                     doSomeStuff();
};

现在,如果我想使用测试,我会:

#include                   "Test.hh"
int                        main() {
  Test                     *test = Test::getInstance();
  test->doSomeStuff();
  return (0);
}

为了解决这个问题,我试图以某种方式"extern"(使用关键字)静态类成员 Singleton::_instance,但我从未成功编译我的应用程序......GCC拒绝这种代码(在Singleton.hpp中):

template<typename T>
extern T                   *Singleton<T>::_instance;

以下内容需要移出singleton.hpp。正如所写的那样,它为每个包含 singleton.hpp 的.cpp文件创建一个指针实例。

template<typename T>
T                       *Singleton<T>::_instance = NULL;

请记住,这是一个定义,而不是一个声明。因此,包含标头的每个对象文件现在都在定义 Singleton::_instance。如果多个.cpp文件包含 singleton.h 并在单个目标(可执行文件或库)中实例化具有相同类型的模板,您将获得多重定义的符号。

若要使此代码正确,需要选取单个.cpp文件(在单一实例模板的客户端中)并在那里定义_instance。这显然不是非常可取的,因此请考虑不使用单例(您的第一个最佳选择)或使用不同的单例模式。