以某种方式在某些类之间共享不同对象的最佳方式是什么?
例如,类A可以将带有字符串的对象o作为键存储在寄存器中,而类B可以使用键来访问它。
我的第一个想法是创建一个寄存器(单例),它有一个哈希表作为成员,使用字符串作为键,void指针作为值。但是必须有一个更好的解决方案吗?
答案 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)
我建议你必须注册的所有类都有一个共同的超类型。
例如,如果您必须存储类One
,Two
和Three
的实例,则可以定义一个(可能为空)类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*>
。
如果您不能拥有一个超类型(例如,因为您无法更改One
,Two
或Three
),您可以查看Boost.Variant。同样,您可以声明A<boost::variant<One, Two, Three> >
。
答案 2 :(得分:1)
第一个问题是:B
如何知道存储对象的类型,
它能用它做什么?也许最简单的解决方案就是
每种类型都有一个注册表。或者,像
可以使用boost::variant
,或者您可以确保所有类型都派生
从一个公共基础,并存储指向它的指针。除非你真的
需要支持多态性(例如,在没有的情况下操作对象)
知道它的确切类型),我会避免使用指针解决方案。
答案 3 :(得分:0)
最好的方法是使用shared_ptr
而不是裸指针。如果您有符合C ++ 11的编译器,则shared_ptr
位于std
命名空间中。否则,请使用Boost实现。