如何由派生类更新抽象类上的受保护变量?

huangapple go评论125阅读模式
英文:

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

问题

The code you provided seems to be in C++, and it appears you want to have a common vector variable shared among all derived classes. However, you are experiencing an issue where menu.showVector() doesn't display the pushed back values from menu2.

To achieve your desired behavior, you should use a static member variable for the commonVector in the base class, which will be shared among all derived classes. Here's a modified version of your code:

#include <iostream>
#include <vector>

using namespace std;

class Menu
{
protected:
    static vector<int> commonVector; // Make it static to be shared among all instances.

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

vector<int> Menu::commonVector; // Define the static member variable.

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;
}

With this modification, commonVector is now shared among all derived classes, and when you call menu1.showVector(), it will display values pushed by both menu1 and menu2.

英文:

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&lt;iostream&gt;
#include&lt;vector&gt;

using namespace std;

class Menu
{

    protected:
    vector&lt;int&gt; commonVector;

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


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

    void addNumber(int i) override
    {
    commonVector.push_back(i);
        cout &lt;&lt; &quot;number added&quot; &lt;&lt; endl;
    }
};

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

    void addNumber(int i) override
    {
    commonVector.push_back(i);
        cout &lt;&lt; &quot;number added&quot; &lt;&lt; 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?

答案1

得分: 1

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 ...
英文:

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&amp; menu): _menu{menu} {}  // as mentioned in the comments, doesn&#39;t need to be explicit
  void addNumber(int i)
  {
    _menu.addNumber(i);  // make Menu::addNumber a public non virtual method
  }
 private:
  Menu&amp; _menu;
};

Then in main:

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

答案2

得分: 0

The comments' suggestion to make it static is appealing but will hurt your project in the long run. static members variables and functions are hard to maintain and offer little testability and mockability.

The right way here is to add a MenuDirectory class. Each menu can have an optional MenuDirectory. In your derived Menu1 and menu2, you check if the base Menu has a MenuDirectory. If it does you call addNumber on it. When the base Menu needs to check all the options, it queries its MenuDirectory.

英文:

The comments' suggestion to make it static is appealing but will hurt your project in the long run. static members variables and functions are hard to maintain and offer little testability and mockability.

The right way here is to add a MenuDirectory class. Each menu can have an optional MenuDirectory. In your derived Menu1 and menu2, you check if the base Menu has a MenuDirectory. If it does you call addNumber on it. When the base Menu need to check all the option, it queries its MenuDirectory.

huangapple
  • 本文由 发表于 2023年3月20日 22:34:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/75791631.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定