Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: recommended design pattern for subsets of class functionality?

I am seeking advice on a design pattern that is a good fit to my needs:

Within my C++ project, one particular pure-virtual class will represent the superset of all related functionality for a certain concept, and the concrete classes derived from that pure-virtual class will each be some different limited subset of that superset. Only 1 instance of any of these concrete classes will exist at runtime.

If I were programming in C, I would likely choose to implement this as a struct of function pointers, with NULLs for any missing functionality. But that doesn't feel very satisfying for C++.

About the only idea I can think of is a class with every member function as 'protected', and a matching set of 'public' member function pointers. The constructors would be responsible for initializing the MFPs to either NULL or the address of the appropriate member function, depending on what functionality that class provides.

But that is really only marginally more C++-ish than the C-struct-of-function-pointers that I first mentioned above. And, perhaps it is good enough. But I am wondering if anyone can suggest a more satisfying, insightful design pattern for this scenario.

I am open to any generally accepted practice. STL is fine.

UPDATE: The reason why the MFP approach isn't very satisfying, is that I will have to implement do-nothing stubs for the ones that don't apply-- because of the pure-virtual base class-- even though I would be setting their respective MFPs to NULL. On further reflection, this update was completely bogus. (They will not be do-nothing stubs, they will be the functionality that is useful, in the cases where NULL isn't used for the MFPs. I think I was tired.)

UPDATE 2: An analogy: My project supports hardware modules that can be swapped out. They are all basically the same category of functionality, but vary in features and capability. At startup, I must detect which hardware module is actually attached, and instantiate the appropriate class. But I don't want the code that uses that class to have special knowledge of each of the classes; I want the class to advertise what functionality it is providing. (Sometimes, two hardware modules will identify as the same type ID, but upon a capabilities probe, one will indicate functionality that the other does not.)

like image 995
Ryan V. Bissell Avatar asked Oct 20 '22 19:10

Ryan V. Bissell


1 Answers

Your design requirement violates a very important OOP principle. If a class or a function depended upon that "superset" interface, then the compiler would never be able to enforce type-safety - you'd essentially be fighting against it, and for what?

I recommend that you segregate your interfaces, and make one concrete (possibly pure virtual) class that implements all of them. This design pattern has a name - it's called facade.

Update I now read your update, and I believe you need a facility for promoting objects. There are 2 kinds of promotions:

  • Implementation promotions:
    This is where you essentially replace the implementation of an object. This can either be done by the state pattern, or by placement-newing your object to one with a different VTABLE.
  • Functionality promotions:
    This is where you add functionality, as in more functions. You can do this by having a map from a name of a hardware module to a variant pointer of it. When you promote an object to a different class, you simply replace the pointer variant. E.g., if your first mapping was from "COM1" -> GenericSerial*, then you now set "COM1" -> SpecializedSerial*. You can work with a variant library such as boost's.
like image 165
Yam Marcovic Avatar answered Oct 28 '22 23:10

Yam Marcovic