سؤال

وأنا أكتب التطبيق قليلا سخيفة في C ++ لاختبار واحدة من المكتبات الخاصة بي. أود التطبيق لعرض قائمة من الأوامر للمستخدم، تسمح للمستخدم اكتب الأوامر، ومن ثم تنفيذ الإجراءات المرتبطة هذا الأمر. يبدو بسيطا بما فيه الكفاية. في C # أنا في نهاية المطاف كتابة قائمة / خريطة من الأوامر مثل ذلك:

    class MenuItem
    {
        public MenuItem(string cmd, string desc, Action action)
        {
            Command = cmd;
            Description = desc;
            Action = action;
        }

        public string Command { get; private set; }
        public string Description { get; private set; }
        public Action Action { get; private set; }
    }

    static void Main(string[] args)
    {
        var items = new List<MenuItem>();

        items.Add(new MenuItem(
            "add",
            "Adds 1 and 2",
            ()=> Console.WriteLine(1+2)));
    }

وأي اقتراحات بشأن كيفية تحقيق ذلك في C ++؟ أنا لا أريد حقا لتعريف الفئات منفصلة / وظائف لكل أمر. يمكنني استخدام Boost، ولكن ليس TR1.

هل كانت مفيدة؟

المحلول

وهناك تقنية شائعة جدا لاستخدام مؤشرات الدالة، أو تعزيز :: وظيفة، فهرستها من قبل اسم العنصر، أو من خلال وجود ناقلات منهم والفهرسة تلاه مؤشر البند لهذه المهمة. مثال بسيط باستخدام اسم العنصر:

void exit_me(); /* exits the program */
void help(); /* displays help */

std::map< std::string, boost::function<void()> > menu;
menu["exit"] = &exit_me;
menu["help"] = &help;

std::string choice;
for(;;) {
    std::cout << "Please choose: \n";
    std::map<std::string, boost::function<void()> >::iterator it = menu.begin();
    while(it != menu.end()) {
        std::cout << (it++)->first << std::endl;
    }

    std::cin >> choice;
    if(menu.find(choice) == menu.end()) {
        /* item isn't found */
        continue; /* next round */
    }   

    menu[choice](); /* executes the function */
}
لايوجد

وC ++ ميزة امدا بعد، ولذلك عليك حقا لاستخدام وظائف لهذه المهمة، للأسف. يمكنك استخدام دفعة :: امدا، ولكن لاحظ انها مجرد محاكاة lambdas، وليس في أي مكان بالقرب قوية مثل حل الأصلي:

menu["help"] = cout << constant("This is my little program, you can use it really nicely");

لاحظ استخدام ثابت (...)، لأن خلاف ذلك تعزيز :: أن امدا لا تلاحظ أن هذا يفترض أن يكون التعبير امدا: إن المترجم محاولة لإخراج السلسلة باستخدام الأمراض المنقولة جنسيا :: cout، وتعيين النتيجة (في اشارة الأمراض المنقولة جنسيا :: ostream) إلى القائمة [ "مساعدة"]. يمكنك الاستمرار في استخدام دفعة :: وظيفة، لأنه سوف يقبل كل شيء يعود باطل والذين لا الحجج - بما في ذلك كائنات وظيفة، وهو ما يعزز :: امدا يخلق

إذا كنت حقا لا نريد وظائف منفصلة أو تعزيز :: امدا، يمكنك أن تأخذ فقط طباعة متجه من أسماء العنصر، ثم switch على عدد بند معين من قبل المستخدم. وربما هذا هو أسهل وأكثر مباشرة الطريق إلى الأمام للقيام بذلك.

نصائح أخرى

لماذا لا الميناء فقط C # رمز لC ++؟ هناك القليل من العمل الذي يتعين القيام به، ولكن شيئا من هذا القبيل يجب أن تحصل على أكثر من عمل عمله الخاص بك:

using std::string;
class MenuItem    
{        
    public:
        MenuItem(string cmd, string desc, boost::function<bool()> action):Command(cmd),
                                                                          Description(desc),
                                                                          Action(action) 
        {}
        boost::function<bool()> GetAction() { return Action; }
        string GetDescription() { return Description; }
        string GetCommand() { return Command; }
    private:
        string Command;
        string Description;
        boost::function<bool()> Action;
}

مع أن تعرف، يا الرئيسية () يمكن استخدام الأمراض المنقولة جنسيا :: قائمة، واستخدام حلقة في حين بسيط () أن يتحقق قيمة الخروج من العمل وMENUITEM لتحديد ما إذا كان ينبغي الخروج.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top