0

Let's say there is a base class

class Base
{
}

and the user has created a new subclass

class NewDerivedClass : public Base
{
}

There is also a enum for all the subclasses:

enum SubclassId
{
    Derived1_Id,
    Derived2_Id,
    ...
    NewDerivedClass_Id  // User has to add this line
}

Now, there is also a factory which creates derived instances based on the SubclassId:

class SubclassFactory
{
    Base* CreateSubclassInstance(SubclassId subclassId)
    {
        switch(subclassId)
        {
            case SubclassId::Derived1_Id:
                return new Derived1(params);
            case SubclassId::Derived2_Id:
                return new Derived2(params);
             ...

            // User has to add the following lines:
            case SubclassId::NewDerivedClass_Id:
                return new NewDerivedClass(params);
        }
    }
}
  1. How can I force the user of my Base class to add new Id in enum?
  2. How can I force the user of my Base class to create it's instance in SubclassFactory?

In the best case I would like to see a compile-time error. Unit test solution to this problem is also acceptable.


Additional information.
1. Users of the Base class create new subclasses in the client side.
2. My code operates in the backend. I get the subclass id remotely and use Factory to make instances of the subclasses created by client programmers.

Egor Okhterov
  • 478
  • 2
  • 9
  • 34
  • What do you mean by a _unit test solution_? – Ron Feb 16 '18 at 14:55
  • Ok, why would You like to achieve this? – bartop Feb 16 '18 at 14:55
  • @Ron, by unit-test solution I mean a googletest which reports error in case the user has created it's own subclass, but he has forgotten to extend the body of `SubclassFactory`. – Egor Okhterov Feb 16 '18 at 14:57
  • 2
    By requiring that users of your base class modify an existing enum every time they add a derived type, you are limiting the extensibility that polymorphism provides. Presumably, if you need a distinct type ID for every derived type, it's because you will eventually care about the concrete type of your objects. In most cases, proper use of polymorphism implies that you should not care about the concrete types. Consider where you will be using those IDs and how you will handle the addition of new types. It's likely polymorphism isn't the right solution to your problem. – François Andrieux Feb 16 '18 at 14:59
  • @bartop, I want the members of the other team to see that they have made a mistake as soon as possible. – Egor Okhterov Feb 16 '18 at 14:59
  • @Pixar Please [update](https://stackoverflow.com/posts/48829298/edit) your post with the relevant information. – Ron Feb 16 '18 at 14:59
  • Just use template parameter for creating subclass, if they have made mistake, they will definitely see that :) – Elvis Oric Feb 16 '18 at 15:00
  • @Elvis, I am getting the id of the subclass from the network in run-time. I cannot use templates for that (probably). And I use Factory to create my own instance. – Egor Okhterov Feb 16 '18 at 15:02
  • @François Andrieux, maybe you're right, but I cannot change the mechanism which was established way before me. – Egor Okhterov Feb 16 '18 at 15:07
  • Nothing to force that in C++. Comments in the code in the header around Base, team meetings to share the knowledge. If a wayward developer does not abide by that, then get HR involved. – Eljay Feb 16 '18 at 15:10
  • @Pixar If each derived type is required to return it's own ID, such as having a pure virtual function for that purpose, then defining that new ID becomes part of deriving your base type. An implementer would necessarily need to provide an override for that function and necessarily return some value from that override. If the documentation or comments are at all clear, the implementer would have no choice but to add a new id to the enum. Though this doesn't address the problem of adding a new entry to the factory function. – François Andrieux Feb 16 '18 at 15:13
  • might help: https://stackoverflow.com/questions/9975672/c-automatic-factory-registration-of-derived-types – PiotrNycz Mar 01 '18 at 11:47

0 Answers0