Search code examples
c++inheritancemenuabstract-classprotected

How can I update a protected variable on the abstract class by its derived classes?


I would like to define an abstract Menu class, from which all the derived classes can inherit the functions, but i want that all derived classes can update a single protected vector variable on the abstract class.

So far i've tried this piece of code:

#include<iostream>
#include<vector>

using namespace std;

class Menu
{

    protected:
    vector<int> commonVector;

    public:
    virtual void display() = 0;
    virtual void addNumber(int i) = 0;
    void showVector() {
        for (auto i :commonVector)
        {
            cout << i << endl; 
        }
    }
};


class Menu1 : public Menu
{
    public:
    void display() override
    {
        cout << "That is the first menu" << endl;
    }

    void addNumber(int i) override
    {
    commonVector.push_back(i);
        cout << "number added" << endl;
    }
};

class Menu2 : public Menu
{
    public:
    void display() override
    {
         cout << "That is the second menu" << endl;
    }

    void addNumber(int i) override
    {
    commonVector.push_back(i);
        cout << "number added" << endl;
    }
};


int main()
{
    Menu1 menu1;
    Menu2 menu2;

    menu1.display();
    menu2.display();

    menu1.addNumber(3);
    menu1.addNumber(5);
    menu2.addNumber(3);
    menu2.addNumber(4);

    menu1.showVector();
    
    cin.get();

    return 0;
}

Problem is that i can indeed update the commonVector variable by its derived classes, but when I tried to display values, using menu.showVector(), I was expecting to see the pushed back values by menu2 as well. What can i do to make sure all classes can get the values with the modified data by the derived classes?


Solution

  • Your design seems to be wrong. Note that if you only use Menu1 class it will still not work as you wish:

    Menu1 m1;
    Menu1 m2;
    m1.addNumber(1);
    m2.addNumber(2);
    // m1 has only 1, m2 has only 2
    

    because m1 and m2 are different instances.

    Instead of "is" relation you probably want "has" relation, or composition instead of inheritance. E.g.: your Menu1 and Menu2 can take a reference to Menu and update it together using its' public interface.

    class Menu1 { // Menu2 similar, if you still need it and if it differs from Menu1
     public:
      Menu1(Menu& menu): _menu{menu} {}  // as mentioned in the comments, doesn't need to be explicit
      void addNumber(int i)
      {
        _menu.addNumber(i);  // make Menu::addNumber a public non virtual method
      }
     private:
      Menu& _menu;
    };
    

    Then in main:

    Menu m;
    Menu1 m1{m};
    Menu1 m2{m};
    // etc ...