如何在C ++中使用CRTP以避免虚拟成员函数的开销?
Answers:
有两种方法。
第一个是通过为类型的结构静态指定接口:
template <class Derived>
struct base {
void foo() {
static_cast<Derived *>(this)->foo();
};
};
struct my_type : base<my_type> {
void foo(); // required to compile.
};
struct your_type : base<your_type> {
void foo(); // required to compile.
};
第二个方法是避免使用引用基语或指针基语,并在编译时进行接线。使用上面的定义,您可以具有如下所示的模板功能:
template <class T> // T is deduced at compile-time
void bar(base<T> & obj) {
obj.foo(); // will do static dispatch
}
struct not_derived_from_base { }; // notice, not derived from base
// ...
my_type my_instance;
your_type your_instance;
not_derived_from_base invalid_instance;
bar(my_instance); // will call my_instance.foo()
bar(your_instance); // will call your_instance.foo()
bar(invalid_instance); // compile error, cannot deduce correct overload
因此,在函数中结合使用结构/接口定义和编译时类型推导,可以执行静态分配而不是动态分配。这是静态多态性的本质。
not_derived_from_base
它不是源自base
,也不是源自base
……
我一直在寻找关于CRTP的不错的讨论。Todd Veldhuizen的《科学C ++技术》是此(1.3)和许多其他高级技术(如表达式模板)的重要资源。
另外,我发现您可以在Google图书中阅读Coplien最初撰写的大多数C ++ Gems文章。也许情况仍然如此。
dynamic_cast
虚拟方法。
此维基百科的答案有你所需要的。即:
template <class Derived> struct Base
{
void interface()
{
// ...
static_cast<Derived*>(this)->implementation();
// ...
}
static void static_func()
{
// ...
Derived::static_sub_func();
// ...
}
};
struct Derived : Base<Derived>
{
void implementation();
static void static_sub_func();
};
尽管我不知道这实际上能为您带来多少收益。虚函数调用的开销是(当然,取决于编译器):
CRTP静态多态性的开销为: