设计一个环绕的菜单? C++/面向对象编程

Posted

技术标签:

【中文标题】设计一个环绕的菜单? C++/面向对象编程【英文标题】:Designing a menu that wraps around? C++ / OOP 【发布时间】:2012-09-11 05:45:23 【问题描述】:

我是一名新程序员,试图自学 C++ 和 OOP。现在我正在处理一个具有多个状态的项目,这是我第一次尝试更大的编程任务/挑战。现在我正在尝试处理一个简单的菜单状态类,但我不确定如何设计它来做我想做的事。具体来说,我是一名初级程序员,我不确定要使用哪些数据类型或模板。

以下是我想要制作的菜单屏幕类型的简要说明:

我正在尝试制作一个简单的菜单屏幕,其中列出了多个“菜单元素”每个“菜单元素”都包含一个字符串(用于显示元素或项目的名称)和一个功能(用于更改状态、屏幕、执行任务等)。 --我想要的菜单系统的其他“功能”是选择环绕的能力。例如,如果菜单有 3 个项目,我希望用户能够按上下键来切换当前选择的元素,如果用户在最后一个元素(#3)上并再次按下,他们会回滚围绕元素#1。 (反之亦然..)

现在,我〜认为〜这将需要我创建一个名为“MenuElement”的新类,以及一个名为“MenuState”的类,它包含并允许用户在特定元素之间切换和选择。

作为一名新的、自学成才的 C++ 程序员,我对一些更高级的容器的经验有限,而且我更熟悉简单的 c 样式数组。我对向量有一点经验,对链表、映射和树也有一点了解,但我不确定在这种情况下使用哪种容器类型。我以前见过使用指针创建循环链表的示例,但该示例是用 C 语言编写的,看起来有点笨拙。 是否有最适合我的问题的特定类型的包含?还是我想太多了,我应该选择一个并运行它?

我想我最终可以使用带有一系列条件语句的 MenuElements 数组来启动并运行这个系统。然而,我真的很想学习如何改进我的编程和设计,不仅让我的代码运行得更快,而且让我的代码干净且逻辑结构合理。

【问题讨论】:

MenuElement 很好,MenuState 我不确定。我将有一个名为MenuMenuPicker 的类,它将保存MenuElements 的集合、当前菜单状态并处理处理菜单的事件(keyup、keydown、enter 等)。至于环绕,我认为没有必要在您的数据结构中处理它。只需在代码中处理它,MenuElements 的简单向量对我来说似乎很好。有趣的任务扩展供您思考,您将如何处理子菜单? IE。一个菜单元素,当您选择它时会打开另一个菜单。 向量迭代器是否总是默认环绕,或者使用条件语句来改变第一个和最后一个菜单元素的行为是否正常?作为一名新程序员,我倾向于使用“MenuElement array[3]”与“int currentSelection”配对。当程序检测到 keydown 事件时,它只是将 currentSelection 增加 1。然后我将使用 if 语句来更改数组最后一个位置的行为。但这对我来说似乎是错误的......哈哈。 我会使用 if 语句。 C++ 中没有标准的循环数据结构,仅仅为了这个简单的目的编写循环数据结构似乎太过分了。 【参考方案1】:

环绕可以用模算术完成,即给定一个名为idx_的私有成员索引变量,活动光标到菜单元素数组中,你可以有一个成员函数page_down()page_up(),比如这个

void CompositeMenu::page_down()

    // idx_ will always remain in the interval [0, num_elements() )
    // when idx_ equals num_elements() - 1, page_down() will yield 0 (i.e. wrap-around)
    idx_ = (idx_ + 1) % num_elements(); 


void CompositeMenu::page_up()

    // idx_ will always remain in the interval [0, num_elements() )
    // when idx_ equals 0, page_up() will yield num_elements() - 1 (i.e. wrap-around) 
    idx_ = (idx_ - 1 + num_elements() ) % num_elements() ;

其中num_elements() 是当前菜单的大小。

对于您的一般设计问题,您的类层次结构草图将使用复合设计模式 (Wikipedia)。这定义了一个名为IMenu 的抽象菜单接口,并将CompositeMenuLeafMenu 派生为具体类。这允许嵌套子菜单的任意级别

class IMenu

public:
    virtual void SomeOperation() = 0;
;

class CompositeMenu
:
    public IMenu

public:
    virtual void SomeOperation() 
     
        // your implementation 
    

    void page_down();  // use implementation above      
    void page_up();    // use implementation above
    int num_elements  return subMenus_.size(); 

private:
    std::vector<IMenu*> subMenus_; // list of subMenus, which can also have nested menus themselves
    int idx_; // active menu element
;

class LeafMenu
:
    public IMenu

public:
    virtual void SomeOperation()
    
        // your implementation
    
;

请注意,由于num_elements() 是一个允许对子菜单进行动态更新的成员函数(即,它允许拖放菜单项)。

【讨论】:

我相信那句话是未定义的行为。在一个语句中修改一个变量两次。更好的是++idx; idx = idx % num_elements_; @john Tnx,已更新。我现在只需加或减 1,然后取模。

以上是关于设计一个环绕的菜单? C++/面向对象编程的主要内容,如果未能解决你的问题,请参考以下文章

Python之面向对象

如何在C语言里实现“面向对象编程”

Java面向对象编程 -1

Java类与对象

我想用java编一个计算器,面向对象编程

嵌入式C语言面向对象编程 --- 总结