-1

我习惯使用dynamic polymorphism并且一切正常,但是在阅读了关于static polymorphism我的结论后,我得出结论,后者克服了动态的开销。

以下是动态多态性的一些开销:

  • 每次调用虚拟方法的额外间接(指针取消引用)。

  • 虚拟方法通常不能内联,这对一些小方法来说可能是一个重大的成本损失。

  • 每个对象的附加指针。在当今流行的 64 位系统上,这是每个对象 8 个字节。对于携带少量数据的小对象,这可能是一个严重的开销。

谁能Static polymorphism用一个非常简单的例子向我解释。什么情况下我应该使用它而不是动态的?

我找到了这个例子,但很抱歉我不明白。它看起来模棱两可:

#include <iostream>
using namespace std;

template <typename Child>
struct Base
{
    void interface()
    {
        static_cast<Child*>(this)->implementation();
    }
};

struct Derived : Base<Derived>
{
    void implementation()
    {
        cerr << "Derived implementation\n";
    }
};

int main()
{
    Derived d;
    d.interface();  // Prints "Derived implementation"
}
4

2 回答 2

2

我们先来分析下你发送的代码编译后会发生什么。编译器将生成两个类,在方法接口内部,它将指针移动到 Derived 对象所在的地址,并使用该指针调用方法实现。

所以现在我们唯一的开销是我们应该为每个派生类生成更多的类(我的意思是二进制代码)。

你现在缺少什么?

考虑以下代码:

Base* base;

if(a)
  base = new DerivedA;
else
  base = new DerivedB;

base->interface();

变量 a 的值仅在运行时才知道,因此您只能对其使用动态多态性。

如果它是静态多态性,您应该告诉派生类的类型。

Base<DerivedA> * base;
Base<DerivedB> * base;

这不允许您根据运行时上下文做出决定。

于 2017-11-24T00:01:53.847 回答
1

静态多态是函数重载的替代名称。这是一个方便的功能,它可以让您避免重命名函数只是为了获取一组替代参数。

当函数在运行时决定时,它与动态多态性完全正交,动态多态性是一种实际的调度机制。

注意:动态多态性的开销是如此之小,以至于你不应该考虑它,直到你分析程序并看到开销很大。这种情况很少发生。

于 2017-11-23T23:44:22.180 回答