Here's a design problem that I haven't been able to find a satisfying solution for. Title reflects what I think I want, but I'm definitely open to suggestions.
I have a struct that holds some data about a command. Sort of like this:
enum class CommandType {
COMMAND1,
COMMAND2
};
struct DataStruct {
CommandType commandType;
std::string someParam;
int someData;
///etc
};
I have a base class that parses chunks of data and populates the struct, and defines some virtual functions that do some operations on based on the parsed commandType
and params.
class Base : public QObject
{
Q_OBJECT
public:
Base() {}
virtual ~Base() {}
virtual void parse(/* some bytes */){
DataStruct s;
/* populate struct fields */
/* do common interface stuff with s */
Func(s); //do subclass specific stuff with s
}
virtual void Func(DataStruct s) = 0;
};
class Derived : public Base
{
Q_OBJECT
public:
Derived() : Base() {}
virtual ~Derived() {}
virtual void Func(DataStruct s) override {
switch(s.commandType){
case CommandType::COMMAND1:
cout << "Here";
break;
case CommandType::COMMAND2:
cout << "There";
break;
}
}
};
The unsatisfying part is, the different subclasses implement the same core set of commands, but there are also some commands that are specific to the subclass type. My current approach requires me to put all of these specific commands into the same enum as the core commands, which works but I would prefer the base class to not have to change every time a new command is added to a subclass or have any "knowledge" of subclass specific functionality at all ideally.
My original half-baked idea was to have each subclass have its own enum of commands, move the commandType
parsing into the subclasses so that they can choose a value from their appropriate enum, and make the commandType
templated, but this doesn't work because virtual functions can't be templated and QObjects can't be templated classes. I didn't show them in my example, but both the base and derived classes use meta objects and signals/slots.
I also do not want to use boost
if possible. Would this be the type of situation to use a QVariant
for storing a value from an arbitrary enum? If so, how would I safely convert back to the correct enum + value that I started with?