Nav*_*K N 5 c++ function-pointers
我正在制作音译工具.我有两个模块lexer和翻译器.Lexer从输入文本中生成标记.根据当前选择的语言,我必须调用适当的翻译例程.
我提出了几个想法来做到这一点.第一个是创建一个被调用的基类,base_translator并提供虚拟方法(translate()),每个翻译都必须覆盖它.现在创建一个工厂translator_factory并create()使用语言名称进行调用.该工厂将返回适当的实例.
但这似乎超过了工程.所以我提出了另一种方法,我有一个如下所示的结构.
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)
这种方法非常简单易于维护.但我想知道,这是解决问题的最佳方法吗?你有什么建议让这更好吗?
任何帮助都会很棒.
对于只有两个项目的情况,您的第二种方法可能看起来更简单(对我来说,它不是......),但从长远来看,它更容易出错并且难以维护。每当添加一种新语言时,您都需要至少在两个地方修改代码。(相信我:即使这对你来说目前看来不太可能,但它几乎不可避免地会发生......)如果你忘记更新你的循环边界,你的代码中就会有一个无声的错误。此外,这种实现比多态实现慢得多:您需要在每次调用之前迭代数组并比较字符串(而不是在 vtable 中查找指针)。
我肯定会使用工厂。除了上述优点之外,它是一种众所周知的设计模式,使其更易于理解。因此,追随你维护代码的人不会那么诅咒你;-)
更新:工厂还可以返回函数指针。在这种情况下,我仍然会在内部使用仿函数,因为这些是成熟的类,具有上面列出的所有优点。还有一个没有明确提到的:它们(作为真实对象)可以存储状态,而普通函数则不能。这可能会在以后产生很大的影响,并大大简化你的设计。当然,一旦您有了工厂接口,您就可以轻松地将其产品的内部表示从普通函数更改为函子(或返回)。