构建控制台菜单类层次结构的最佳方法?

6 c++ python oop class

我已经在C++和Python中创建了一个控制台菜单,但我认为这里的语言不是很重要,因为我在询问类的结构.

所以我想要实现的是一个类似于MS-DOS的菜单,我可以在其中拥有父菜单(文件夹)和操作菜单(文件).这是打印机在控制台中看起来的样子:

[-] Root directory
        Open snakegame
    [-] First sub directory
            Print out stupid messages
        [+] Closed directory in open directory
            Shutdown computer
    [+] These directories are closed
    [+] You can't see the content inside them
        Quit menu
Run Code Online (Sandbox Code Playgroud)

如你所见,我在这里有两种菜单;

  1. 目录(MS-DOS文件夹)菜单,其中包含其他菜单.激活后,它们会打开/关闭.例如:Root directory现在打开,您可以看到其中的所有菜单.如果它关闭,[-]转入[+],你看不到任何其他菜单.
  2. 动作(MS-DOS文件)菜单,链接到一个函数.激活后,他们会调用他们链接的功能.例如:Open snakegame可以链接到一个函数startSnakeGame(),这将关闭菜单并启动蛇游戏.

我已经编写了两个工作实现来获得想要的结果,我只是想知道,我应该使用哪一个?第一种方式是,我只有一个被调用的类Menu,它将所有成员变量和方法编码到一个类中.另一种方式是,我将这两种不同类型的菜单分成两个类,其中有一个共同的基类.


下面是一些成员变量,我现在将它们分成三个部分(基类,目录类和动作类),但它们可以组合成一个类.

基本菜单:

  • parent= this/self作为子项保存在列表/向量内的菜单(目录一)(见下文).
  • label =显然是打印菜单时显示的标签.
  • selected =布尔值,告诉当前菜单是否被选中(由鼠标指向).

目录菜单:

  • subMenus =列表或向量(在C++中),其中包含其他菜单.
  • open =一个布尔值,告诉菜单打开或关闭.

动作菜单:

  • action =指向此菜单激活时调用的函数的指针.

正如你所看到的,也有从其他类不同只是几个变量,它可以被设定为如果action == 0(没有动作),那么菜单会自动更改open,以false/true取决于它的当前值.这种方式动作菜单将被终止,并且只有动作菜单将保持subMenus并且closed不使用.


这可能完全取决于一个人的意见,但我一直在考虑这个问题,并且找不到一种优于其他方式的方法,它们都有自己的优点和缺点,而且两者都运作良好.所以我问你的意见,我很想知道是否有人有任何理由为什么他们选择一个而不是另一个.基本上我是在问原因,我不在乎你的意见.

除了文件夹和文件之外,没有其他菜单类型,因此基类不能用于其他任何内容.


编辑:关于如何使用菜单的简单Python和C++示例:

Python只有一个类:

# Using default param. here to set "action = None" or "action = toggleOpen()"
root = Menu(None, "Root directory")
snake = Menu(root, "Open snakegame", startSnakeGame)
sub1 = Menu(root, "First sub directory")
printMsg = Menu(sub1, "Print out stupid messages")
...
Run Code Online (Sandbox Code Playgroud)

Python有多个类:

# With multiple classes, action parameter no longer exists
root = DirectoryMenu(None, "Root directory")
snake = ActionMenu(root, "Open snakegame", startSnakeGame)
...
Run Code Online (Sandbox Code Playgroud)

C++与一个类:

Menu* root = new Menu(0, "Root directory");
Menu* snake = new Menu(&root, "Open snakegame", &startSnakeGame);
...
Run Code Online (Sandbox Code Playgroud)

具有多个类的C++:

DirectoryMenu* root = new DirectoryMenu(0, "Root directory");
ActionMenu* snake = new ActionMenu(&root, "Open snakegame", &startSnakeGame);
...
Run Code Online (Sandbox Code Playgroud)

第二编辑:我只在Python中实现了两种方式,而在C++中只实现了一种方式.所以我开始用C++编写多类方法,只是为了好玩和练习,我遇到了一个问题; 有一个基类,我不能添加this到父的subMenus-vector,因为基类不拥有subMenus,基类不能知道DirectoryMenu.

所以我将不得不破解我的方式,这是一个大减去.除非有人能想出一个好的方法来实现它吗?

BaseMenu::BaseMenu(BaseMenu* parent)
: m_parent(parent) // works
{
    m_parent->addSubMenuk(this); // BaseMenu doesn't have Directory's addSubMenu()
}    
Run Code Online (Sandbox Code Playgroud)

小智 0

这两种方式在性能等方面非常接近,所以有点难以弄清楚。然而,选择其中之一的原因有一个:OOP 中的逻辑和规则。我必须将其分为 3 类:BaseMenuActionMenuDirectoryMenu

解决这里的“两个类无法相互了解”问题可以像iogane gamba puti fon gu建议的那样完成。然而,定义抽象方法addSubMenu()removeSubMenu()inBaseMenu与只有一个类一样违反规则,因此这不是另一种方法的选择。

我最终得到的是使用回调并重载pointer( *)运算符。它现在返回一个指向另一个类的实例的指针,并根据类型调用它的方法。