通过变量使用对象和对象函数

时间:2013-09-29 14:30:12

标签: c++ class object

程序背景:用户只能输入两个单词string - 动词和名词。我将此字符串标记为vector并将tokens[0]vector个允许的动词进行比较,将tokens[1]vector个允许的名词进行比较。

现在,我正试图找到一种方法,只允许对某些名词执行某些动词。例如,写“拿书”会给出一条消息(或者其他什么)说它是允许的,但写“拿门”不会。到目前为止,我为每个可能的动词创建了一个class对象,其值为bool(例如,在class Object中,我可以为Object book创建一个m_take = true ,或false的{​​{1}}。

但是,我无法将这些对象与用户输入相关联。例如,我希望能够做到这样的事情:
1)用户输入“动词名词”,它作为Object doortokens[0]进入代币向量。
2)程序检查输入是否包含可接受的单词(单独) 3)考虑tokens[1]是检索对象可能的操作的bool值的函数,程序检索getstat(),如果tokens[1].getstat(tokens[0]),则执行true(例如。tokens[0].tokens[1]())。这样,我的book.take()中只能有一个if周期,所有合法动词和名词都可以使用这个周期,而不会创建main()if的无限列表,等,手动考虑每个选项。

很抱歉,这一点令人困惑。我知道不可能将变量用作对象名称,但我确信有更好的方法可以做到这一点,而不是在考虑动词和名词的每一个混合和匹配的周期内进行循环。我现在正在尝试各自的3个,但是一旦我开始工作,我计划扩展它,如果我必须多次对每个可能的动词和名词进行硬编码,那么跟踪每个变化将是一场噩梦。源代码。 (另外,抱歉没有发布整个来源 - 这是一个非常长的文件!) 感谢您提供正确方向的任何帮助/提示!

3 个答案:

答案 0 :(得分:2)

您可以将运行时多态性用于此类内容,使用virtual方法或C ++ 11 std::function和lambdas。

您显然必须重新设计“令牌”系统。


虚拟方法示例:

struct Object
{ 
    virtual void onTake() { }
    virtual void onOpen() { }
};

struct Door : public Object 
{
    bool open{false};
    void onTake() override { say("I can't take the door!"); }
    void onOpen() override { say("The door is now open."); open = true; }
};

struct Book : public Object
{
    void onTake() override { say("I put the book in my backpack."); }
    void onOpen() override { say("I open the book. All the pages are blank."); }
};

C ++ 11 lambdas示例:

struct Object
{ 
    std::function<void()> onTake, onOpen;
};

struct Door : public Object 
{
    bool open{false};
    Door() 
    {
        onTake = []{ say("I can't take the door!"); };
        onOpen = []{ say("The door is now open."); open = true; };
    }
};

struct Book : public Object
{
    Book() 
    {
        onTake = []{ say("I put the book in my backpack."); };
        onOpen = []{ say("I open the book. All the pages are blank."); };
    }
};

// You can also avoid creating new classes
Object bananaPrototype; 
bool eaten{false};
bananaPrototype.onTake = []{ say("I put the banana in my backpack."); };
bananaPrototype.onOpen = [eaten] mutable 
{ say("I eat the banana. Yum."); eaten = true; };

答案 1 :(得分:0)

很难在没有看到代码的情况下给出一个非常简单的建议,但据我所知,你最好考虑放弃硬编码方法,即 book.take()。 尝试编写更多通用代码,至少类似book.action(actions::kTake)

答案 2 :(得分:0)

如你所说,tokens[0].tokens[1]()没有达到你想要的效果 - 在运行程序时,函数和变量的名称不可用。

您可以尝试使用地图。 objects可以是包含对象名称键的地图。价值(objects[token[0]])反过来又是其他地图,可以做你想做的事情(objects[token[0]][token[1]])。

以下是一个例子:

#include <unordered_map>
#include <string>
#include <iostream>

using namespace std;

void read_fn()
{
    cout << "You read the book";
}

int main()
{
    unordered_map <string, unordered_map <string, void (*)()>> lookup;

    unordered_map <string, void (*)()> book_lookup;

    book_lookup["read"] = read_fn;
    lookup["book"] = book_lookup;

    lookup["book"]["read"]();
}