C++ CRTP 避免动态多态
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/262254/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
CRTP to avoid dynamic polymorphism
提问by Dean Michael
How can I use CRTP in C++ to avoid the overhead of virtual member functions?
如何在 C++ 中使用 CRTP 来避免虚拟成员函数的开销?
回答by Dean Michael
There are two ways.
有两种方法。
The first one is by specifying the interface statically for the structure of 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.
};
The second one is by avoiding the use of the reference-to-base or pointer-to-base idiom and do the wiring at compile-time. Using the above definition, you can have template functions that look like these:
第二种方法是避免使用基址引用或基址指针的习惯用法,并在编译时进行接线。使用上面的定义,您可以拥有如下所示的模板函数:
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
So combining the structure/interface definition and the compile-time type deduction in your functions allows you to do static dispatch instead of dynamic dispatch. This is the essence of static polymorphism.
因此,在函数中结合结构/接口定义和编译时类型推导,您可以进行静态分派而不是动态分派。这就是静态多态的本质。
回答by fizzer
I've been looking for decent discussions of CRTP myself. Todd Veldhuizen's Techniques for Scientific C++is a great resource for this (1.3) and many other advanced techniques like expression templates.
我一直在寻找有关 CRTP 的体面讨论。Todd Veldhuizen 的Techniques for Scientific C++是此 (1.3) 和许多其他高级技术(如表达式模板)的重要资源。
Also, I found that you could read most of Coplien's original C++ Gems article at Google books. Maybe that's still the case.
此外,我发现您可以在 Google 图书上阅读 Coplien 的大部分原始 C++ Gems 文章。也许情况仍然如此。
回答by Roger Lipscombe
I had to look up CRTP. Having done that, however, I found some stuff about Static Polymorphism. I suspect that this is the answer to your question.
我不得不查找CRTP。然而,这样做之后,我发现了一些关于Static Polymorphism 的东西。我怀疑这就是你问题的答案。
It turns out that ATLuses this pattern quite extensively.
事实证明,ATL非常广泛地使用这种模式。
回答by user23167
ThisWikipedia answer has all you need. Namely:
这个维基百科答案有你需要的一切。即:
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();
};
Although I don't know how much this actually buys you. The overhead of a virtual function call is (compiler dependent, of course):
虽然我不知道这实际上给你买了多少。虚函数调用的开销是(当然取决于编译器):
- Memory: One function pointer per virtual function
- Runtime: One function pointer call
- 内存:每个虚函数一个函数指针
- 运行时:一个函数指针调用
While the overhead of CRTP static polymorphism is:
而CRTP静态多态的开销是:
- Memory: Duplication of Base per template instantiation
- Runtime: One function pointer call + whatever static_cast is doing
- 内存:每个模板实例化 Base 的重复
- 运行时:一个函数指针调用 + static_cast 正在做的任何事情