【问题标题】:How to execute a class method by string input in C++如何在 C++ 中通过字符串输入来执行类方法
【发布时间】:2021-05-29 03:50:42
【问题描述】:

我正在尝试用 C++ 开发一个文本冒险,用户可以在其中输入字符串命令(例如“take apple”)。 这是我想出的一个非常天真的代码示例:

# include <iostream>     
using namespace std;

class fruit{
    public:
        string actual_name;
        fruit(string name){
            actual_name = name;
        }
        take() {
            cout << "You take a " << actual_name << "." << endl;
        }
};

fruit returnObjectFromName(string name, fruit Fruits[]){
    for(int i = 0; i <= 1; i++){  // to be modified in future depending on Fruits[] in main()
        if (Fruits[i].actual_name == name)
            return Fruits[i];
        }
}

int main(){
    string verb;
    cout << "Enter verb: ";
    cin >> verb;
    string object;
    cout << "Enter object: ";
    cin >> object;
    fruit apple("apple");
    fruit Fruits[] = { apple }; // to be extended in future
    // returnObjectFromName(object, Fruits). ??? ()
}

如果这可能的话,我怎么可能用类似于函数 returnObjectFromName 的方法获得水果方法? 我(独立地)开始使用 Python 进行开发,在那里我至少可以使用 eval(),但据我所知,在 C++ 中这不是一个选项。 我也尝试使用地图,但我没有设法使其与方法一起使用。

谢谢大家的回答。

【问题讨论】:

  • 您可能正在寻找std::mapstd::unordered_map
  • 等等...我可能读错了。 returnObjectFromName(object, Fruits).my_fruit_method(); 应该可以工作。如果它不适合您,请使用代码示例扩展您的问题描述,准确显示您尝试过的内容,以便我们向您展示如何纠正它。
  • 旁注:如果name 无法匹配,returnObjectFromName 将无法到达返回语句。这对程序来说是致命的。当一个函数承诺返回一个值时,它必须在每种情况下都返回一个值。
  • 旁注:for循环退出条件中的&lt;=通常是一个错误。例如:注意for(int i = 0; i &lt;= 1; i++)i 的可能值。第一次迭代i 为 0。0 i++ 将 i 增加到 1。1 Fruits[1],所以程序失败了。也许它会大声失败并崩溃或吐出废话。也许它失败得如此悄无声息,以至于您不会立即注意到。也许你几周都没有注意到。也许直到你把程序展示给你的老板,或者在贸易展上,或者自动驾驶汽车没有刹车时,你才注意到。
  • 在 C 和 C++ 中,您不能即时创建方法。您可以做的最接近的方法是将术语映射到现有功能。 std::map&lt;std::string, std::function&lt;void ()&gt;&gt;verbs = { { "take", take_function }, { "eat", eat_function } };。然后你可以verb.at(user_action)(); 调用user_action 中字符串的函数。如果user_action 不包含已知字符串,at 将抛出异常。

标签: c++ string input methods


【解决方案1】:

在 C++ 中依赖反射不是好方法,我认为没有办法在类中列出方法。也许你可以使用函数指针,但指向实例方法的指针是地狱。

我建议使用多态性和良好的设计。如果有些物品可能会被拿走,那么使用这样的界面:

#include <iostream>

using namespace std;

class ITakeable {
    public:
        virtual bool isTakeable() = 0;
        virtual void take() = 0;
        virtual void cannotTake() = 0;
};

class fruit : public ITakeable {
    public:
        string actual_name;
        
        fruit(string name){
            actual_name = name;
        }
        
        bool isTakeable() {
            return true;
        }
        
        void take() {
            cout << "You take a " << actual_name << "." << endl;
        }
        
        void cannotTake() {
            cout << "not needed to be implemented";
        }
};

class airplane : public ITakeable {
    public:
        string actual_name;
        
        airplane(string name){
            actual_name = name;
        }
        
        bool isTakeable() {
            return false;
        }
        
        void take() {
            cout << "not needed to be implemented";
        }
        
        void cannotTake() {
            cout << "You CANNOT take a " << actual_name << "." << endl;
        }
};


int main() {
   fruit apple("apple");
   
   if (apple.isTakeable()) {
       apple.take();
   }
   
   airplane plane("boeing");

   if (plane.isTakeable()) {
       plane.take();
   } else {
       plane.cannotTake();
   }
   
   // use of interface in general
   
   ITakeable * something = &apple;

   if (something->isTakeable()) {
       something->take();
   }
   
   something = &plane;

   if (something->isTakeable()) {
       something->take();
   } else {
       something->cannotTake();
   }

   return 0;
}

【讨论】:

【解决方案2】:

由于fruit是用户定义的类型,因此您必须为您的类型声明自己的方法,或者从先前定义的方法继承。

“内置”字符串类型有很多方法 在 python 中执行与 eval (...) 几乎相同的工作。

我还注意到你的函数不需要在水果类之外独立定义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-26
    • 2012-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多