英文:
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<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?
答案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& 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 ...
答案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
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论