如何在某些类之间共享不同的对象

时间:2012-04-02 11:49:47

标签: c++ templates

以某种方式在某些类之间共享不同对象的最佳方式是什么?

例如,类A可以将带有字符串的对象o作为键存储在寄存器中,而类B可以使用键来访问它。

我的第一个想法是创建一个寄存器(单例),它有一个哈希表作为成员,使用字符串作为键,void指针作为值。但是必须有一个更好的解决方案吗?

4 个答案:

答案 0 :(得分:2)

从您的澄清:

template <typename OB>
class A {
  std::unordered_map<std::string, OB> hash;
public:
  OB const& get(std::string const&) const;
  void add(OB const& object, std::string const&);
};

也就是说,A<int>是一个按名称存储int个对象的类,A<std::set<float>>是一个按名称存储浮点数的类。你不能混合它们。这与基本的C ++哲学一致:theA.get("foo")的类型是在编译时确定的,而不是在运行时放入的内容。

在C ++中,您可以“混合”多个派生类型,如果您需要针对您的特定情况。这有点复杂:

template <typename Base>
class A {
  std::unordered_map<std::string, std::unique_ptr<Base>> hash;
public:
  Base const& get(std::string const&) const;
  template<typename Derived> void add(std::string const& name, Derived const& object)
  {
    std::unique_ptr<Base> copy(new Derived(object));
    hash.emplace(std::make_pair(name, std::move(copy)));
  }
};

这里有一些轻微的诡计,因为hash应该是副本的唯一所有者,但它是在外部构建的,因此需要移动它。 (对于额外的幻想,我可以添加一个Derived&&重载来消除该副本)

答案 1 :(得分:1)

我建议你必须注册的所有类都有一个共同的超类型。 例如,如果您必须存储类OneTwoThree的实例,则可以定义一个(可能为空)类Object,您的类可以从中派生:

class Object {} 
class One : public Object { /* One's member and methods */ }
class Two : public Object { /* Two's member and methods */ }
class Three : public Object { /* Three's member and methods */ }

如果您关注MSalters question,则可以声明A<Object*>

如果您不能拥有一个超类型(例如,因为您无法更改OneTwoThree),您可以查看Boost.Variant。同样,您可以声明A<boost::variant<One, Two, Three> >

答案 2 :(得分:1)

第一个问题是:B如何知道存储对象的类型, 它能用它做什么?也许最简单的解决方案就是 每种类型都有一个注册表。或者,像 可以使用boost::variant,或者您可以确保所有类型都派生 从一个公共基础,并存储指向它的指针。除非你真的 需要支持多态性(例如,在没有的情况下操作对象) 知道它的确切类型),我会避免使用指针解决方案。

答案 3 :(得分:0)

最好的方法是使用shared_ptr而不是裸指针。如果您有符合C ++ 11的编译器,则shared_ptr位于std命名空间中。否则,请使用Boost实现。