我正在尝试为我要编写的一个小程序实现一个菜单结构。
MenuItem 包含一个标签、一个关联函数、一个到其父级的链接和一个包含对其子级的引用的向量。然后是Menu,主要负责选择一个新的MenuItem,并跟踪当前哪个Item处于活动状态。不幸的是,当我在 Menu 中使用 MenuItem 并将当前的 MenuItem 更改为它的一个子项时,我无法再进一步,因为以下子项列表为空。似乎向量没有被正确复制。我试图实现一个复制构造函数,但这没有帮助。这是我的来源如下。
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
typedef void (*fptr)(int);
using namespace std;
void test(int i)
{
cout << "test function called with argument: " << i << endl;
}
class MenuItem
{
private:
vector<MenuItem*> children;
string label;
fptr f;
MenuItem* parent;
public:
MenuItem(string newLabel, fptr newFunction = NULL):label(newLabel),f(newFunction)
{
}
void addChild(MenuItem& mi)
{
mi.parent = this;
children.push_back(&mi);
}
MenuItem* getChild(int i)
{
return children[i];
}
MenuItem* getParent()
{
return parent;
}
string getLabel()
{
return label;
}
int countChildren()
{
return children.size();
}
void list()
{
vector<MenuItem*>::iterator i;
for(i = children.begin(); i < children.end(); ++i)
{
MenuItem* m = *i;
label = m->label;
stringstream s;
s << (i - children.begin());
cout << s.str() << ": " << label << endl;
}
}
void invoke(int i)
{
f(i);
}
};
class Menu
{
private:
MenuItem* current;
public:
Menu(MenuItem* m)
{
current = m;
open(0);
}
void open(int i)
{
current = current->getChild(i);
if(current->countChildren() > 0)
{
cout << "[" << current->getLabel() << "]" << endl;
current->list();
}
else
current->invoke(i);
}
void back(int i)
{
current = current->getParent();
}
};
int main() {
MenuItem m1("Root");
MenuItem m2("List Media");
MenuItem m6("List Movies",&test);
MenuItem m7("List Music",&test);
MenuItem m8("List Games",&test);
MenuItem m9("List Books",&test);
MenuItem m3("Find Media");
MenuItem m10("Find Movies",&test);
MenuItem m14("Find by title",&test);
MenuItem m15("Find by genre",&test);
MenuItem m11("Find Music",&test);
MenuItem m16("Find by title",&test);
MenuItem m17("Find by genre",&test);
MenuItem m12("Find Games",&test);
MenuItem m18("Find by title",&test);
MenuItem m19("Find by genre",&test);
MenuItem m13("Find Books",&test);
MenuItem m20("Find by title",&test);
MenuItem m21("Find by genre",&test);
MenuItem m4("Add Media");
MenuItem m22("Add Movie",&test);
MenuItem m23("Add Music",&test);
MenuItem m24("Add Game",&test);
MenuItem m25("Add Book",&test);
MenuItem m5("Delete Media");
MenuItem m26("Add Movie",&test);
MenuItem m27("Add Music",&test);
MenuItem m28("Add Game",&test);
MenuItem m29("Add Book",&test);
m1.addChild(m2);
m2.addChild(m6);
m2.addChild(m7);
m2.addChild(m8);
m2.addChild(m9);
m1.addChild(m3);
m3.addChild(m10);
m10.addChild(m14);
m10.addChild(m15);
m3.addChild(m11);
m11.addChild(m16);
m11.addChild(m17);
m3.addChild(m12);
m12.addChild(m18);
m12.addChild(m19);
m3.addChild(m13);
m13.addChild(m20);
m13.addChild(m21);
m1.addChild(m4);
m4.addChild(m22);
m4.addChild(m23);
m4.addChild(m24);
m4.addChild(m25);
m1.addChild(m5);
m5.addChild(m26);
m5.addChild(m27);
m5.addChild(m28);
m5.addChild(m29);
Menu m(&m1);
int option;
while(1){
cout << "Media Library> ";
cin >> option;
m.open(option);
}
}