I would like to get rid of dynamic casting. What is the best alternative?

Viewed 95

I send data to and from my server.

I create a message, set the type (enum) and the objects that need to be transferred.

The message is sent as a compressed JSON string. When I receive it I parse the message, instantiate the object and start to fill it. When I need to instantiate the data transferred I use a map that contains the name of the class as a key and a pointer to the constructor as the value.

All this works fine but now I need to consume the message and do what needs to be done with it (send an answer, write to the DB, etc). What is the best way to do that ? For now, I check the type of the message and get each of the transferred object. But I don't know what class they are (not explicitly).

Should I dynamic cast everything (cost a lot for not much) ? Should I treat the data with the hope it will always be in the same order. Or should I store the objects as a map (with the name or a enum as the key) and cast it correctly then ?

I know that dynamic casting should not be done if possible. But here I am wondering, is it worth it to have a switch from the beginning and create the correct object and feed it the JSON ? For now the entire message is reconstructed dynamically without any problem and my message manager will handle the treatment, should I change that ?

1 Answers

I agree with Peter.

I'd probably use a "sniffer" function that returned an enum class JType mapping the JSON to the associated type of the message.

Then use that JType enum in a switch/case block to call the appropriate factory function which would return a std::unique_ptr.

Failure to parse would throw an exception, rather than return a unique_ptr with a nullptr.

  • You'd have one factory for each associated class type.
  • You'd have a sniffer function that would determine what type the JSON represented, returning an enum.
  • The happy path would be JType e = sniff(message);, and if (e == JType::Foo) std::unique_ptr<Foo_t> foo = FooFactory(message);
  • Throwing an exception from the factory would only occur in the exceptional case of the message and the factory disagreeing as to what should be in the message.

No list of base_class objects, but the enum class JType would have a 1:1 mapping to the classes.

Think of the JSON as being the state information "dehydrated", and the factory functions "rehydrate" the state data into new objects. The factory functions could be static class functions as part of the class, or could be freestanding functions.

Hierarchies are for polymorphism, and this isn't that situation.

Related