Search code examples
c++inheritancepolymorphism

Problem isolating a piece of c++ code using polymorphic inheritance


I'm trying to rewrite a piece of code in c++ to isolate a piece of code that I would like to use only in some of the children of a particular object.

I've created a very simplified version of the code just to analyze the problem:


class SaverInterface {
protected:
    virtual void saveData(int data) = 0;
};

class SaverImpl : public SaverInterface {
protected:
    void saveData(int data) override {
        std::cout << "data to save: " << data << std::endl;
    }
};

class ObjectA : public SaverInterface {
public:
    void save(int data) {
        saveData(data);
    }
};

class ComposedObjectA : public ObjectA, public SaverImpl {
public:
    void publicSave() {
        save(1);
    }
};

int main() {
    auto* objectA = new ComposedObjectA();
    objectA->publicSave();

    delete objectA;
    return 0;
}

The idea is that I have different ways of saving some data and I would like to abstract that operation in the intermediate object (ObjectA), calling the pure virtual function of the interface (SaverInterface), that is implemented in an other object (SaverImpl).

In my "final" composed object (ComposedObjectA) I've tried to derive from both the ObjectA and SaverImpl, thinking that the compiler would take the saveData function implementation from the SaverImpl, but it's not working, and the compiler gave me back the error "unimplemented pure virtual method 'publicSave' in 'ComposedObjectA'".

I'm relatively new to the polymorphism (I've written code for years in language that haven't that option) so I'm probably assuming something that the compiler cannot do... Someone could explain me why that code couldn't work?

Any suggestion on different approach to solve the situation?

Thanks to all Cheers Mix


Solution

  • You have a diamond inheritance problem. If you really want to continue down this path, you will need to use virtual inheritance (so : public SaverInterface becomes : virtual public SaverInterface in both places).
    Demo

    However, do you really want inheritance in this case? What does it mean for ObjectA to be a Saver? Does it just mean that is has a saveData member function? In this case, why not use a function pointer instead?

    Example:

    class SaverInterface {
    protected:
        using SaveDataFunction = void (*)(int);
    
        SaverInterface(SaveDataFunction saveData) : saveData(saveData) {}
    
        SaveDataFunction saveData;
    };
    
    class ObjectA : public SaverInterface {
    public:
        ObjectA(SaveDataFunction saveDataFunction) : SaverInterface(saveDataFunction) {}
    
        void save(int data) {
            saveData(data);
        }
    };
    

    Demo

    You can either keep the SaverInterface class or just implement the function pointer directly in ObjectA.