たとえば、私はそのようなものを持つことができます、
A
B
ba
bb
C
Ca
D
現在、2D配列がありますが、これはあまり一般的ではありません。最大サブレベルを2から3に拡張する場合は、別の次元が必要になるためです。何か提案はありますか?
たとえば、私はそのようなものを持つことができます、
A
B
ba
bb
C
Ca
D
現在、2D配列がありますが、これはあまり一般的ではありません。最大サブレベルを2から3に拡張する場合は、別の次元が必要になるためです。何か提案はありますか?
複合パターンは、ここで適切なアプリケーションになります。
(ウィキペディアから:) http://en.wikipedia.org/wiki/Composite_pattern
あなたの場合:
各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
};
使用法:
MenuNode menu("root"),
file("File"),
edit("Edit"),
open("Open..."),
close("Close"),
save("Save..."),
prefs("Preferences"),
yes_foo("Activate Foo"),
no_foo("Deactivate Foo");
menu.Add(&file);
menu.Add(&edit);
file.Add(&open);
file.Add(&close);
file.Add(&save);
edit.Add(&prefs);
prefs.Add(&yes_foo);
prefs.Add(&no_foo);
以下を表します。
Main Menu
File
Open...
Close
Save...
Edit
Preferences
Activate Foo
Deactivate Foo
この例の明らかな欠陥、(おそらく) 一時変数のアドレスへの依存に注意してください。これを関数で作成して返すことはできません。
実装の些細な部分も欠落しています。たとえば、サンプル コードではノードのプライベート ステートをトラバースする方法がありません。
sampson-chen が言及した Composite デザイン パターンは、メニュー構造からいくつかのテスト メソッドを選択できる、小さな開発者モニター用に私が行った実装の正しい方法でした。
サブメニューとリーフ (メニュー エントリ) を派生させる基本クラス「メニュー エントリ」があります。リーフは何かを実行するだけですが、サブ メニューは別のメニュー レベルを開きます。
たとえば、基本クラスは次のようになります (shared_pointers を使用する場合)。
/*************************************************************//*!
* @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;
}
};
select メソッドでは、何かを実行するリーフがあるかどうか、またはポインターを変更する必要があるサブメニューがあるかどうかを戻り値で確認します。
便宜上、表示するサブメニューのすべての子メニューエントリを見つけるメソッド、または実際のメニューパスなどを含むタイトル行を作成するメソッドを追加できます...別のアイデアは、メニューツリーをスキャンするメソッドです二重のメニューエントリ asf を避けるために。
ツリーを使用します。とにかく、これはツリーで最もよく定義されます。
ここで、rootNodeは、、、に接続されてA
いB
ます。とに接続されています。に接続されています。等C
D
B
ba
bb
C
Ca