能否用静态多态实现动态多态的所有功能?
Can I achieve all the functionality of dynamic polymorphism with static polymorphism?
我习惯使用 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"
}
静态多态性是函数重载的另一种名称。这是一个方便的功能,它可以让您避免重命名函数只是为了采用一组替代参数。
当函数在 运行 时决定时,它与动态多态性完全正交,动态多态性是一种实际的调度机制。
注意:动态多态性的开销很小,在分析程序并发现开销很大之前,您不应该考虑它。这种情况很少发生。
我们先分析一下你发来的代码编译后会发生什么。编译器会生成两个classes,在方法接口内部,它只是将指针移动到Derived对象所在的地址,并用该指针调用方法实现。
所以现在我们只有开销,就是我们应该为每个派生的 class(我的意思是二进制代码)生成更多的 classes。
你现在缺少什么?
考虑以下代码:
Base* base;
if(a)
base = new DerivedA;
else
base = new DerivedB;
base->interface();
变量a的值只有在运行时才知道,所以只能对其使用动态多态
如果是静态多态,你应该告诉派生的类型是什么class。
Base<DerivedA> * base;
Base<DerivedB> * base;
哪个不允许您决定,具体取决于运行时上下文。
我习惯使用 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"
}
静态多态性是函数重载的另一种名称。这是一个方便的功能,它可以让您避免重命名函数只是为了采用一组替代参数。
当函数在 运行 时决定时,它与动态多态性完全正交,动态多态性是一种实际的调度机制。
注意:动态多态性的开销很小,在分析程序并发现开销很大之前,您不应该考虑它。这种情况很少发生。
我们先分析一下你发来的代码编译后会发生什么。编译器会生成两个classes,在方法接口内部,它只是将指针移动到Derived对象所在的地址,并用该指针调用方法实现。
所以现在我们只有开销,就是我们应该为每个派生的 class(我的意思是二进制代码)生成更多的 classes。
你现在缺少什么?
考虑以下代码:
Base* base;
if(a)
base = new DerivedA;
else
base = new DerivedB;
base->interface();
变量a的值只有在运行时才知道,所以只能对其使用动态多态
如果是静态多态,你应该告诉派生的类型是什么class。
Base<DerivedA> * base;
Base<DerivedB> * base;
哪个不允许您决定,具体取决于运行时上下文。