c++inheritance

One variable with multiple possible classes?


I have the following scenario:

  1. I have a bunch of classes A, B, ..., and all of them expose the same API, void functions start and stop.
  2. Depending on user choice, the program must run the start function of the chosen class.
  3. At some later time, depending on user choice, they can run the stop function.
  4. Go back to step 1.

I thought I could just make some Base class with some start and stop API, and have all the other classes inherit from Base. The idea was then to initialize Base myVar and then do A myVar when the user choice is given, but that would imply that myVar would have different classes on different branches, and the compiler complains.

An alternative is to define one variable for each class, but then there's a lot of duplication of code.

Is there any way to only have one single variable and only branch once on user choice? E.g., after defining myVar once, just use myVar.start() and myVar.stop() everywhere.


Solution

  • You are on the right track with wanting a Base class to unify the interface. But, you are trying to use myVar in an incorrect way which doesn't allow you to accomplish what you want.

    You need myVar to be a pointer to the Base class, and then you can create the appropriate descendant class to have myVar point at.

    Try something more like this:

    class Base {
    public:
        virtual ~Base() = default;
        virtual void start() = 0;
        virtual void stop() = 0;
        ...
    };
    
    class A : public Base {
    public:
        void start() override { ... }
        void stop() override { ... }
        ...
    };
    
    class B : public Base {
    public:
        void start() override { ... }
        void stop() override { ... }
        ...
    };
    
    std::unique_ptr<Base> myVar;
    ...
    if (user chose A) {
        myVar = std::make_unique<A>();
    }
    else if (user chose B) {
        myVar = std::make_unique<B>();
    }
    ...
    myVar->start();
    ...
    myVar->stop();