How to share different objects between some classes

What is the best way to share different objects between some classes in a general way?

For example, class A can store an object o with a string as a key in a register, and class B can access it using the key.

My first idea was to create a register (singleton) that has a hash table as a member, using a string as key and a void pointer as value. But there must be a better solution for this?

+3


source to share


4 answers


From your clarification:

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

      

That is A<int>

, it is a class that stores int

objects by name, and it A<std::set<float>>

is a class that stores sets of floats by name. You cannot mix them. This is in line with the basic C ++ philosophy: the type theA.get("foo")

is determined at compile time, not by what you insert at runtime.



In C ++, you can "mix" multiple derived types if you need it for your particular case. This is a little more complicated:

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

      

There are a few minor tricks here, as it hash

should be the sole owner of the copy, but it is built externally and therefore needs to be moved. (For extra fantasy, I could add an overload Derived&&

that also removes this copy)

+2


source


I would assume that all the classes you must register have a common supertype. For example, if you need to store instances of classes One

, Two

and Three

, you can define a (possibly empty) class Object

from which your class can get:

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

      



If you follow the MSalters question , you can declare A<Object*>

.

If you don't have one supertype (for example, because you can't change One

, Two

or Three

), you can look at Boost. Option . Again, you can declare A<boost::variant<One, Two, Three> >

.

+1


source


The first question is, how do you B

know the type of the stored object, and what can it do about it? Perhaps the simplest solution is to simply have one registry for each type. Alternatively, something like boost::variant

, or you can ensure that all types come from a common base and store a pointer to that. If you actually need to support polymorphism (for example, work on an object without knowing its exact type), I would avoid the pointer solution.

+1


source


The best way is to use shared_ptr

instead of a public pointer. If you have a C ++ 11 compatible compiler shared_ptr

is in the namespace std

. Otherwise, use the Boost implementation.

0


source







All Articles