10

在这个关于动态多态性的问题中建议使用 CRTP 。然而,据称这种模式只对静态多态有用。正如这里所暗示的,我正在查看的设计似乎受到虚函数调用的快速阻碍。 即使是 2.5 倍的加速也很棒。

有问题的类很简单,可以完全内联编码,但是直到运行时才知道将使用哪些类。此外,他们可能会以任何顺序被束缚,将性能侮辱堆积到伤害上。

欢迎提出任何建议(包括在这种情况下如何使用 CRTP)。

编辑:谷歌搜索出现了函数模板的提及。这些看起来很有希望。

4

3 回答 3

21

多态性的字面意思是多种(多)形式(变形)。在静态类型语言(例如 C++)中,存在三种类型的多态性。

  1. 即席多态性:这在 C++ 中最好被视为函数和方法重载。相同的函数名称将根据调用的参数的编译时类型与函数或方法签名的匹配来绑定到不同的方法。
  2. 参数多态性:在 C++ 中,这是模板以及您可以用它做的所有有趣的事情,例如 CRTP、专业化、部分专业化、元编程等。同样的这种多态性,相同的模板名称可以根据模板做不同的事情参数是编译时多态性。
  3. 子类型多态性:最后,当我们听到 C++ 中的多态性这个词时,我们会想到这一点。这是派生类覆盖虚函数以专门化行为的地方。指向基类的相同类型的指针可以根据它指向的具体派生类型具有不同的行为。这是在 C++ 中获得运行时多态性的方法。

如果直到运行时才知道将使用哪些类,则必须使用涉及虚函数调用的子类型多态。

与静态绑定调用相比,虚拟方法调用的性能开销非常小。我敦促您查看此SO 问题的答案。

于 2009-02-25T05:02:11.693 回答
3

我同意 m-sharp 的观点,即您不会避免运行时多态性。

如果您重视优化而不是优雅,请尝试替换 say

void invoke_trivial_on_all(const std::vector<Base*>& v)
{
  for (int i=0;i<v.size();i++)
    v[i]->trivial_virtual_method();
}

有类似的东西

void invoke_trivial_on_all(const std::vector<Base*>& v)
{
  for (int i=0;i<v.size();i++)
  {
    if (v[i]->tag==FooTag)
      static_cast<Foo*>(v[i])->Foo::trivial_virtual_method();
    else if (v[i]->tag==BarTag)
      static_cast<Bar*>(v[i])->Bar::trivial_virtual_method();
    else...
  }
}

它不漂亮,当然不是 OOP(更多的是回归到你可能在好的旧“C”中做的事情),但如果虚拟方法足够简单,你应该得到一个没有调用的函数(取决于足够好的编译器和优化选项)。使用 dynamic_cast 或 typeid 的变体可能更优雅/安全,但要注意这些功能有自己的开销,无论如何可能与虚拟调用相当。

您最有可能从上面看到改进的地方是,如果某些类方法是无操作的,并且它使您免于调用它们,或者如果函数包含常见的循环不变代码并且优化器设法将其从环形。

于 2009-02-25T13:51:13.450 回答
0

您可以走 Ole C 路线并使用工会。尽管这也可能很混乱。

于 2009-02-25T05:41:05.717 回答