根据变量的值执行函数 - C++

Nav*_*K N 5 c++ function-pointers

我正在制作音译工具.我有两个模块lexer和翻译器.Lexer从输入文本中生成标记.根据当前选择的语言,我必须调用适当的翻译例程.

我提出了几个想法来做到这一点.第一个是创建一个被调用的基类,base_translator并提供虚拟方法(translate()),每个翻译都必须覆盖它.现在创建一个工厂translator_factorycreate()使用语言名称进行调用.该工厂将返回适当的实例.

但这似乎超过了工程.所以我提出了另一种方法,我有一个如下所示的结构.

struct translator
{
    const char* name;
    void (*fp)();
};
Run Code Online (Sandbox Code Playgroud)

它只保留一个语言名称和一个可以处理它的函数指针.用法是,

static translator translators[] = {
    {"first", first},
    {"second", second}
};
const char* language = /* */; 
for(int i = 0; i < 2; i++) {
    translator *t = translators + i;
    if(strcmp(t->name, language) == 0) {
        t->fp();
        break;
    }
}
Run Code Online (Sandbox Code Playgroud)

这种方法非常简单易于维护.但我想知道,这是解决问题的最佳方法吗?你有什么建议让这更好吗?

任何帮助都会很棒.

Rom*_*ain 5

这通常是抽象类和虚函数的有福使用案例.我不明白为什么你认为它是"过度工程".... o_O

重点是定义一个契约,以便您的代码可以轻松扩展,"主代码"不必担心实际的实现细节.


Pét*_*rök 3

对于只有两个项目的情况,您的第二种方法可能看起来更简单(对我来说,它不是......),但从长远来看,它更容易出错并且难以维护。每当添加一种新语言时,您都需要至少在两个地方修改代码。(相信我:即使这对你来说目前看来不太可能,但它几乎不可避免地会发生......)如果你忘记更新你的循环边界,你的代码中就会有一个无声的错误。此外,这种实现比多态实现慢得多:您需要在每次调用之前迭代数组并比较字符串(而不是在 vtable 中查找指针)。

我肯定会使用工厂。除了上述优点之外,它是一种众所周知的设计模式,使其更易于理解。因此,追随你维护代码的人不会那么诅咒你;-)

更新:工厂还可以返回函数指针。在这种情况下,我仍然会在内部使用仿函数,因为这些是成熟的类,具有上面列出的所有优点。还有一个没有明确提到的:它们(作为真实对象)可以存储状态,而普通函数则不能。这可能会在以后产生很大的影响,并大大简化你的设计。当然,一旦您有了工厂接口,您就可以轻松地将其产品的内部表示从普通函数更改为函子(或返回)。