CRTP来避免dynamic多态性
如何在C ++中使用CRTP来避免虚拟成员函数的开销?
有两种方法。
第一个是通过静态指定types结构的接口:
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. };
第二个是避免使用reference-to-base或pointer-to-base习语,并在编译时进行连线。 使用上面的定义,你可以使用如下的模板函数:
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
所以在你的函数中结合结构/接口定义和编译时types的推导,你可以做静态调度而不是dynamic调度。 这是静态多态的本质。
我一直在寻找CRTP的体面讨论。 Todd Veldhuizen的科学C ++技术是这个(1.3)和许多其他高级技术(如expression式模板)的很好的资源。
另外,我发现你可以在Google书籍上阅读Coplien最初的C ++ Gems文章。 也许情况仍然如此。
我必须查找CRTP 。 但是,做了这些之后,我发现了一些关于Static Polymorphism的东西。 我怀疑这是你的问题的答案。
事实certificate, ATL相当广泛地使用这种模式。
这维基百科答案有你需要的一切。 即:
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(); };
虽然我不知道这实际上买了多less钱。 虚函数调用的开销是(当然是依赖于编译器):
- 内存:每个虚函数一个函数指针
- 运行时:一个函数指针调用
虽然CRTP静态多态性的开销是:
- 内存:每个模板实例的基础重复
- 运行时:一个函数指针调用+无论static_cast正在做什么