摘要:如何在C++中创建单例mixin?我试图避免复制相同的get_instance()函数,私有(private)构造函数等。但是我无法找出一种使它成为mixin的方法,因为静态实例将由继承自mixin的所有对象共享。

使每个派生类成为单例很容易,但是有没有一种方法可以做到而又不重复代码?非常感谢您的帮助,我很沮丧。

代码:
我正在编写一个带有Registry类的程序,用于按名称查找对象。

#include <string>
#include <memory>
#include <map>
#include <string>
#include <assert.h>

template <typename T>
class Registry
{
private:
  // make private so that the class can't be instantiated and must be used via get_instance
  Registry() {}
protected:
  std::map<std::string, std::shared_ptr<T> > name_to_object_ptr;
public:
  static Registry<T> & get_instance()
  {
    static Registry<T> instance;
    return instance;
  }
  void register_name(const std::string & name, T*obj_ptr)
  {
    assert( name_to_object_ptr.count(name) == 0 );
    name_to_object_ptr[name] = std::shared_ptr<T>(obj_ptr);
  }
  const std::shared_ptr<T> & lookup_name(const std::string & name)
  {
    assert( name_to_object_ptr.count(name) > 0 );
    return name_to_object_ptr[name];
  }
  int size() const
  {
    return name_to_object_ptr.size();
  }
};

我的Registry类是单例;它必须是单例(以便注册的对象不会消失)。
class DerivedRegistryA : public Registry<int>
{
};

class DerivedRegistryB : public Registry<int>
{
};

int main()
{
  DerivedRegistryA::get_instance().register_name(std::string("one"), new int(1));
  std::cout << DerivedRegistryA::get_instance().size() << std::endl;
  DerivedRegistryA::get_instance().register_name(std::string("two"), new int(2));
  std::cout << DerivedRegistryA::get_instance().size() << std::endl;
  DerivedRegistryA::get_instance().register_name(std::string("three"), new int(3));
  std::cout << DerivedRegistryA::get_instance().size() << std::endl;

  DerivedRegistryB::get_instance().register_name(std::string("four"), new int(4));
  std::cout << DerivedRegistryB::get_instance().size() << std::endl;

  return 0;
}

输出:



所需的输出:

最佳答案

lionbest所说的听起来很对。这是一个与您的原始设计更相似的相关想法。

您声明一个模板类,其工作方式类似于Registry对象的工厂。我称它为RegAccess:

template <typename RegType>
class RegAccess
{
public:
  static RegType & get_instance()
  {
    static RegType instance;
    return instance;
  }
};

为使其正常工作,您:
  • 声明RegAccess<Registry<T> >Registry<T>的 friend (要做到这一点,需要确保在Registry<T>之前的某个地方定义了它)
  • 使Registry的构造函数 protected ,而不是私有(private)(以便派生类的构造函数可以隐式使用它)
  • get_instance类定义
  • 中删除Registry<T>方法

    然后您的主程序变为:
    int main()
    {
      RegAccess<DerivedRegistryA>::get_instance().register_name(std::string("one"), new int(1));
      std::cout << RegAccess<DerivedRegistryA>::get_instance().size() << std::endl;
      RegAccess<DerivedRegistryA>::get_instance().register_name(std::string("two"), new int(2));
      std::cout << RegAccess<DerivedRegistryA>::get_instance().size() << std::endl;
      RegAccess<DerivedRegistryA>::get_instance().register_name(std::string("three"), new int(3));
      std::cout << RegAccess<DerivedRegistryA>::get_instance().size() << std::endl;
    
      RegAccess<DerivedRegistryB>::get_instance().register_name(std::string("four"), new int(4));
      std::cout << RegAccess<DerivedRegistryB>::get_instance().size() << std::endl;
    
      return 0;
    }
    

    当我对此进行测试时,它生成了所需的输出。

    09-04 09:36
    查看更多