【问题标题】:This is CRTP usage for static polymorphism but without implementation of a derived function. Compiles both in gcc and visual studio. Why?这是静态多态性的 CRTP 用法,但没有实现派生函数。在 gcc 和 Visual Studio 中编译。为什么?
【发布时间】:2011-01-18 06:18:24
【问题描述】:
#include <iostream>

template <class Derived>
class Base
{
public:
  void method1()
  {
    static_cast<Derived*>(this)->method1();
  }

  void method2()
  {
    static_cast<Derived*>(this)->method2();
  }
};

class Derived1: public Base<Derived1>
{
public:
  void method1()
  {
    std::cout << "Method 1 of Derived1 executed.\n";
  }
};

int main(int argc, char *argv[])
{
  Derived1 d1;
  d1.method1();
  d1.method2();
  return 0;
}

后续问题:如何使这种类型安全?也就是说,如果有人忘记实现方法 2,我希望编译器能够捕获它。我不希望它在运行时爆炸。

【问题讨论】:

  • 出于某种原因,我认为这样的错误会在编译时被发现。有什么方法可以使这种类型安全?
  • 您可以通过基本的 SFISAE 方法检查系统使其类型安全,您可以在 SO 或 google 上的几个问题中找到该系统。
  • @Noah:你是说 SFINAE 吗?而且我不知道如何在这里应用它。

标签: c++ polymorphism crtp


【解决方案1】:

我认为这是有效的原因是如果你实例化这段代码:

void method2()
{
  static_cast<Derived*>(this)->method2();
}

如果Derived 没有method2() 的实现,本质上将是一个美化的自递归调用。这里的原因是,在Derived1中,确实有一个叫method2的成员函数,也就是继承自基类的那个。

我尝试运行这段代码,果然对method2的调用导致了自递归的堆栈溢出。

通常,CRTP 通过不让基类函数调用同名的派生类函数来避免这种情况。这样,如果派生类缺少特定函数,调用会触发编译器错误。在您的情况下,这不会发生,因为函数本身可以从基类间接引用。

【讨论】:

    【解决方案2】:
      Derived1 d1;
      d1.method2();
    

    尽管Derived1 没有定义method2(),它还是通过继承Base 得到它。这就是它编译和运行的原因。 d1.method2() 实际上调用了Base::method2(),它再次调用了自己。这是一个递归调用。

    【讨论】:

      猜你喜欢
      • 2011-08-25
      • 2014-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-29
      相关资源
      最近更新 更多