简体   繁体   English

C ++:奇怪的重复模板模式是什么?并且可以奇怪地重复模板模式取代虚拟功能?

[英]C++: what is the Curiously-Recurring-Template-Pattern? and can Curiously-Recurring-Template-Pattern replace virtual functions?

I don't have a precise description of the problem so I'm just asking if this is possible (and if it is, some other information would be great). 我没有对问题的准确描述,所以我只是问这是否可能(如果是的话,其他一些信息会很好)。

A programmer told me you can avoid runtime overhead caused by virtual functions/polymorphism. 程序员告诉我,你可以避免虚函数/多态导致的运行时开销。 He said to avoid the runtime overhead you can use templates in pattern called Curiously_recurring_template_pattern which looks something like this: 他说为了避免运行时开销,你可以在名为Curiously_recurring_template_pattern的模式中使用模板,它看起来像这样:

class Derived : public Base<Derived>
{
  // ... implementation here
};

How does this Curiously-Recurring-Template-Pattern work? 这个奇怪的重复模板模式如何工作?

How can one use Curiously-Recurring-Template-Pattern to substitute normal virtual functions/polymorphism? 如何使用Curiously-Recurring-Template-Pattern替换正常的虚函数/多态?

Did I get it wrong? 我弄错了吗?

Very specifically, the CRTP can be used instead of a base class with virtual functions to implement the template method pattern without virtual function call overhead. 非常具体地,可以使用CRTP代替具有虚函数的基类来实现模板方法模式而无需虚函数调用开销。

With virtual functions, the TMP looks like this: 使用虚函数,TMP如下所示:

class ProvidesMethod {
protected:
  void Method() {
    // do something
    Part1();
    // do something else
    Part2();
    // do something final
  }

private:
  virtual void Part1() = 0;
  virtual void Part2() = 0;
};

class ExposesMethod : private ProvidesMethod {
public:
  using ProvidesMethod::Method;

private:
  void Part1() {
    // first part implementation
  }
  void Part2() {
    // second part implementation
  }
};

With the CRTP, it looks like this: 使用CRTP,它看起来像这样:

template <typename Derived>
class ProvidesMethod {
protected:
  void Method() {
    // do something
    self().Part1();
    // do something else
    self().Part2();
    // do something final
  }

private:
  Derived& self() { return *static_cast<Derived*>(this); }
  const Derived& self() const { return *static_cast<const Derived*>(this); }
};

class ExposesMethod : private ProvidesMethod<ExposesMethod> {
public:
  using ProvidesMethod<ExposesMethod>::Method;

private:
  friend class ProvidesMethod<ExposesMethod>;
  void Part1() {
    // first part implementation
  }
  void Part2() {
    // second part implementation
  }
};

this is called CRTP (for Curiously Recurring Template Pattern) so you can look it up. 这称为CRTP(用于奇怪的重复模板模式),因此您可以查找它。

Although I don't really see how it could replace classic polymorphism... 虽然我真的没有看到它如何取代经典的多态性......

On the other hand, one can in some cases replace complex hierarchical structure of classes by template, (see policy-based design for more info), but it's not always possible... 另一方面,在某些情况下,可以通过模板替换类的复杂层次结构(有关更多信息,请参阅基于策略的设计),但并不总是可行的......

As Julien noted, this is CRTP. 正如Julien所说,这是CRTP。 You should look it up. 你应该查一查。 But the CRTP cannot replace virtual functions. 但CRTP无法取代虚拟功能。 If it does in a particular case for you, then you didn't actually need virtual functions in the first place. 如果它在特定情况下适用于您,那么您实际上并不需要虚拟功能。 Look, templates provide compile-time polymorphism. 看,模板提供了编译时多态性。 Virtual functions provide run-time polymorphism. 虚函数提供运行时多态性。 If you don't know what which override is going to be called at compile time, then a template based solution isn't going to work. 如果您不知道在编译时将调用哪个覆盖,那么基于模板的解决方案将不起作用。 If you always know what the real type of an object is going to be at runtime, then you don't need virtual functions. 如果您始终知道对象的实际类型在运行时将是什么,那么您不需要虚函数。

I'm not sure how you would use templates to provide something like virtual functions - it seems strange to me - certainly without a bunch of trickery that eventually amounts to implementing your own version of virtual functions instead of using the compiler provideed ones, I find it very hard to see how you can make a way that the code calling the function don't know what type the object is, and call the correct function for that object type. 我不确定你会如何使用模板来提供像虚函数这样的东西 - 这对我来说似乎很奇怪 - 当然没有一堆诡计最终相当于实现你自己的虚函数版本而不是使用编译器提供的那些,我发现很难看出如何使调用函数的代码不知道对象是什么类型,并为该对象类型调用正确的函数。 Which is what virtual functions do. 这是虚函数的功能。

Further, from personal experience, the ACTUAL overhead from virtual functions is very small, and only in very extreme cases does it make a difference (the main case where the non-virtual function becomes inlined, and is so trivial that the overhead of calling a function is a substantial part of the total execution time (which also means the function needs to be called many times for it to make any significant difference). There is MORE overhead if you have to "work out what to do" (using if-statements or something like that) in some other way [other than implementing your own variation on "virtual function", but that's just reinventing the wheel, and unless your new wheel is better than the existing one, that's not a good idea]. 此外,从个人经验来看,虚拟函数的ACTUAL开销非常小,并且只有在非常极端的情况下它才会产生影响(非虚拟函数内联的主要情况,并且调用a的开销非常小)函数是总执行时间的重要部分(这也意味着函数需要被多次调用才能产生任何显着的差异。)如果你必须“弄清楚要做什么”,那就有更多的开销(使用if-)声明或类似的东西)以某种其他方式[除了在“虚拟功能”上实现你自己的变化,但这只是重新发明轮子,除非你的新轮子比现有的更好,这不是一个好主意]。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM