C++ 数据结构,表示可以有子菜单的菜单
比如我可以有这样的东西C++ 数据结构,表示可以有子菜单的菜单,c++,C++,比如我可以有这样的东西 A B ba bb C Ca D 现在我有一个2D数组,但这不是很一般,因为如果我想将最大子级别从2扩展到3,我需要另一个维度。有什么建议吗?复合模式在这里是一个合适的应用: (摘自维基百科:) 就你而言: 创建一个名为“Menu”的基类(对应于上图中的组件部分) 创建一个名为“MenuItem”的派生类(对应于上图中的叶部分) 创建一个名为“SubMenu”的派生类(对应于上图中的复合部分)子菜单可以包含更多菜单-可以是更多菜单项或子菜单 通过对每个子菜单
A
B
ba
bb
C
Ca
D
现在我有一个2D数组,但这不是很一般,因为如果我想将最大子级别从2扩展到3,我需要另一个维度。有什么建议吗?复合模式在这里是一个合适的应用: (摘自维基百科:) 就你而言:
- 创建一个名为“Menu”的基类(对应于上图中的组件部分)
- 创建一个名为“MenuItem”的派生类(对应于上图中的叶部分)
- 创建一个名为“SubMenu”的派生类(对应于上图中的复合部分)子菜单可以包含更多菜单-可以是更多菜单项或子菜单
aSubMenu.add(newMenuItemOrSubMenu)
,aSubMenu
应增加自己的计数器,并用顺序号标记新项。(实现的具体细节由您决定,您根本不必使用单独的计数器,只需使用列表或数组即可)也许:
class MenuNode
{
public:
MenuNode(std::string new_label);
void Add(MenuNode * new_node);
private:
std::string label;
std::vector<MenuNode *> children; // changed to vector to preserve order
};
它代表:
Main Menu
File
Open...
Close
Save...
Edit
Preferences
Activate Foo
Deactivate Foo
注意本例中的明显缺陷,即依赖(可能)临时变量的地址。您将无法在函数中创建并返回它
实现的一些琐碎部分也丢失了,例如,在示例代码中无法遍历节点的私有状态。使用树。无论如何,这最好在树中定义 其中:根节点连接到
A
,B
,C
,D
B
连接到ba
和bb
C
已连接到Ca
。等等
sampson chen提到的复合设计模式是我为小型开发人员监视器所做的实现的正确方式,它允许您从菜单结构中选择一些测试方法 我有一个基类“菜单项”,我从中派生子菜单和叶(菜单项)。叶子只是执行一些东西,而子菜单打开另一个菜单级别 例如,基类可能类似于此(当您喜欢使用共享_指针时):
/***************************************************************************************************************************************/*!
*@简要说明所有菜单项类型(子菜单和子菜单项/项)的基类
******************************************************************/
类菜单项:public boost::从\u中启用\u共享\u
{
公众:
虚拟~MenuEntry(){}
/**************************************************************//*!
*@添加菜单项的简短默认实现;必须重新实现
*@param[in]newSubMenuEntry-新菜单项(另一个子菜单或叶)
**************************************************************/
虚拟空添加(boost::shared_ptr newSubMenuEntry)=0;
/*****************************************************************//*!
*@调用菜单项的简短默认实现;始终返回false
*@return false-该函数尚未重新实现
****************************************************************/
虚拟bool调用(void)
{
//成员函数尚未重新实现
返回false;
}
/*****************************************************************************//*!
*@brief默认实现,必须重新实现
*@return emptyVector-一个空向量
*********************************************************************************/
虚拟std::向量getChildren(void)
{
std::向量空向量;
返回空向量机;
}
/*******************************************************************************//*!
*@brief提供指向实际菜单项父项的指针
*@return m_parent-指向父级的指针
******************************************************************************/
boost::共享的ptr父级(void)
{
返回母校;
}
/***************************************************************************//*!
*@选择菜单项的简短默认实现
*@param[in]desiredMenuEntry-应选择的所需菜单项
*@return notExisting-指向此的指针
**********************************************************************************/
虚拟boost::shared_ptr select(boost::shared_ptr desiredMenuEntry)=0;
/**************************************************************************//*!
*严重性:C0\n\n
*@brief设置指向新菜单项父项的指针
*@param[in]pointerToParent-指向父级的指针
****************************************************************************/
void setParent(boost::shared_ptr pointerToParent)
{
m_parent=指针指向;
}
/***************************************************************************//*!
*@用于销毁子对象的简短默认实现
*****************************************************************************/
虚空破坏(虚空)=0;
受保护的:
/************************************************************************//*!
*@菜单项的简短构造函数(子菜单或叶)
*@param[in]menuEntryName-子菜单或叶的名称
*************************************************************************/
菜单项(标准::字符串菜单项名称)
{
m_menuEntryName=menuEntryName;
}
};
在select方法中,我通过返回值检查是否有一个执行某些操作的叶,或者一个必须更改指针的子菜单
为了方便起见,您可以添加在子菜单中查找所有子菜单项以进行显示的方法,或者添加用实际菜单栏构造标题行的方法
Main Menu
File
Open...
Close
Save...
Edit
Preferences
Activate Foo
Deactivate Foo
/*************************************************************//*!
* @brief The base class for all menu entry types (sub menus and sub menu entries/items)
******************************************************************/
class MenuEntry : public boost::enable_shared_from_this<MenuEntry>
{
public:
virtual ~MenuEntry(){}
/**************************************************************//*!
* @brief Default implementation to add menu entries; has to be re implemented
* @param[in] newSubMenuEntry - the new menu entry (another sub menu or leaf)
**************************************************************/
virtual void add(boost::shared_ptr<MenuEntry> newSubMenuEntry)=0;
/*****************************************************************//*!
* @brief Default implementation for call to menu entries; always returns false
* @return false - the function has not been re implemented
****************************************************************/
virtual bool call(void)
{
// the member function has not been re-implemented
return false;
}
/*****************************************************************************//*!
* @brief Default implementation, has to be reimplemented
* @return emptyVector - an empty vector
*********************************************************************************/
virtual std::vector<boost::shared_ptr<MenuEntry> > getChildren(void)
{
std::vector<boost::shared_ptr<MenuEntry> > emptyVector;
return emptyVector;
}
/*******************************************************************************//*!
* @brief Gives a pointer to the parent of the actual menu entry
* @return m_parent - pointer to the parent
******************************************************************************/
boost::shared_ptr<MenuEntry> parent(void)
{
return m_parent;
}
/***************************************************************************//*!
* @brief Default implementation for selecting a menu entry
* @param[in] desiredMenuEntry - the desired menu entry which shall be selected
* @return notExisting - a pointer to <b>this</b>
**********************************************************************************/
virtual boost::shared_ptr<MenuEntry> select(boost::shared_ptr<MenuEntry> desiredMenuEntry)=0;
/**************************************************************************//*!
* <B>Criticality: C0 \n\n</B>
* @brief Sets a pointer to the parent of new menu entry
* @param[in] pointerToParent - pointer to the parent
****************************************************************************/
void setParent(boost::shared_ptr<MenuEntry> pointerToParent)
{
m_parent = pointerToParent;
}
/***************************************************************************//*!
* @brief Default implementation for destroying children
*****************************************************************************/
virtual void destroy(void)=0;
protected:
/************************************************************************//*!
* @brief Constructor for a menu entry (sub menu or leaf)
* @param[in] menuEntryName - the name for the sub menu or leaf
*************************************************************************/
MenuEntry(std::string menuEntryName)
{
m_menuEntryName = menuEntryName;
}
};
typedef int (*MENU_FUNCTION_POINTER)();
typedef struct _MENU MENU;
typedef MENU* MENU_POINTER;
struct _MENU
{
bool isValid; // C++ can not compare struct is NULL
string text;
MENU_FUNCTION_POINTER func;
bool isOpen;
MENU_POINTER childMenu;
MENU_POINTER parent;
};
class ConsoleMenu
{
private:
static MENU _chapters[];
static MENU _chapter1[];
static MENU _chapter2[];
};
MENU ConsoleMenu::_chapters[] = {
{true, "Chapter 1", NULL, false, ConsoleMenu::_chapter1, NULL},
{true, "Chapter 2", NULL, false, ConsoleMenu::_chapter2, NULL},
{true, "Chapter 3", NULL, false, NULL, NULL},
{true, "Chapter 4", NULL, false, NULL, NULL},
{false, "unused", NULL, false, NULL, NULL}
};
MENU ConsoleMenu::_chapter1[] = {
{true, "Example 1.1", Example1, false, NULL, ConsoleMenu::_chapters},
{true, "Example 1.2", Example2, false, NULL, ConsoleMenu::_chapters},
{false, "unused", NULL, false, NULL, NULL}
};
MENU ConsoleMenu::_chapter2[] = {
{true, "Example 2.1", NULL, false, NULL, ConsoleMenu::_chapters},
{true, "Example 2.2", NULL, false, NULL, ConsoleMenu::_chapters},
{true, "Example 2.3", NULL, false, NULL, ConsoleMenu::_chapters},
{false, "unused", NULL, false, NULL, NULL}
};