1

I got a queue (here for simplification: just a single variable) holding various kinds of messages.

InboxMessage inbox_queue_;

Multiple threads/classes can write messages into that queue. A consumer class reads them and processes them based on the kind of message that has been read.

class StatusMessage : public InboxMessage { 
public:
  std::string getStatus();
  std::string getTimestamp();
  // ...
};

class RandomMessage : public InboxMessage { 
public:
  std::string getCode();
  int getCount();
  // ...   
};

The derived classes hold different kinds of attributes which must be accessed when handling the message.

My question is: is there any way to avoid downcasting by the consumer class in this scenario? Should it be avoided at all costs (if so, then how?).

I'm using dynamic_cast to make sure the program checks if the cast is valid and I can react to bad casts.

Thanks in advance!

bolov
  • 72,283
  • 15
  • 145
  • 224
Lexusminds
  • 335
  • 2
  • 14
  • 1
    Why not a an abstract `virtual` function in the base-class called `process` (or similar) and which is then overridden in the child classes to "process" the messages in the proper way? – Some programmer dude Mar 19 '19 at 07:45
  • If you want to use e.g. member/-functions only `RandomMessage ` owns, you need to downcast (If you know the type use `static_cast`). If you only want to use member/- function declared in `InboxMessage`, you don't need to cast. Note that you'll need `virtual` on the function in the base class, if you want to usea overwritten version of it in the child class. – Korni Mar 19 '19 at 07:45
  • Perhaps that the visitor pattern could help you – Gojita Mar 19 '19 at 07:51
  • Thanks for your answers. I don't know if an abstract 'process' method will work out here. Let me give a clearer explanation. The consumer class will read a, let's say, StatusMessage. While processing that message the consumer has to call various other classes and dependencies. If I put all of that logic into the derived process method, I would have to pass all dependencies and information as a parameter to that method. – Lexusminds Mar 19 '19 at 07:53
  • @Someprogrammerdude I think that's the canonical way to do it. Sometimes the consumers must do special things with the messages they handle though (I see that you said that now in a comment). In that case you can consider the [double dispatch](https://en.wikipedia.org/wiki/Double_dispatch) pattern which calls back the handler from the `process()` in the specific message. Since the message type in its own `process()` implementation is known at compile time the handlers can overload the callback function and take special care of the specific message type they are written to handle. – Peter - Reinstate Monica Mar 19 '19 at 07:56
  • Again, take a look at the visitor pattern. You can see the "process" method stated by the first comment as an "accept" method in the visitor pattern. – Gojita Mar 19 '19 at 07:57
  • Thanks again for your input. I'll have a quick look at the double dispatch pattern and visitor pattern. – Lexusminds Mar 19 '19 at 08:01
  • Seems like the double dispatch is exactly what I've been looking for - thanks a lot :) – Lexusminds Mar 19 '19 at 08:06

1 Answers1

0

Seems like double dispatch is the way to go here. It's basically the visitor pattern with just one kind of visitor calling. Take a look at these links if you're interested:

https://en.wikipedia.org/wiki/Double_dispatch

Double dispatch/multimethods in C++

Lexusminds
  • 335
  • 2
  • 14