7

たとえば、私はそのようなものを持つことができます、

A
B
 ba
 bb
C
 Ca
D

現在、2D配列がありますが、これはあまり一般的ではありません。最大サブレベルを2から3に拡張する場合は、別の次元が必要になるためです。何か提案はありますか?

4

5 に答える 5

7

複合パターンは、ここで適切なアプリケーションになります。

複合パターン

(ウィキペディアから:) http://en.wikipedia.org/wiki/Composite_pattern

あなたの場合:

  • 「メニュー」という基本クラスを作成します(これは上の図のコンポーネント部分に対応します)
  • 「MenuItem」という派生クラスを作成します(これは上の図のLeaf部分に対応します)
  • 「SubMenu」という派生クラスを作成します(これは上の図のCompositeパーツに対応します)。SubMenuには、さらに多くのMenuを含めることができます。これには、より多くのMenuItemまたはSubMenuを含めることができます。

各SubMenuオブジェクトでカウンターを実装することにより、コンポジット「サブメニュー」への挿入順序に基づいてメニュー要素の目的の順序を実現できます。呼び出すたびにaSubMenu.add(newMenuItemOrSubMenu)aSubMenu独自のカウンターをインクリメントし、新しいアイテムに順序番号をタグ付けする必要があります。(実装の正確な詳細はあなた次第です。個別のカウンターを使用する必要はなく、リストまたは配列を使用するだけです)

于 2012-10-23T18:55:17.947 に答える
2

おそらくこれ:

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

この例の明らかな欠陥、(おそらく) 一時変数のアドレスへの依存に注意してください。これを関数で作成して返すことはできません。

実装の些細な部分も欠落しています。たとえば、サンプル コードではノードのプライベート ステートをトラバースする方法がありません。

于 2012-10-23T19:05:48.090 に答える
2

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 を避けるために。

于 2013-04-16T08:21:28.877 に答える
1

ツリーを使用します。とにかく、これはツリーで最もよく定義されます。

ここで、rootNodeは、、、に接続されてABます。とに接続されています。に接続されています。等CDBbabbCCa

ここに画像の説明を入力してください

于 2012-10-23T19:07:49.143 に答える