这是静态多态性的 CRTP 用法,但没有实现派生函数。在 gcc 和 Visual Studio 中编译。为什么?

发布于 2024-10-12 05:56:35 字数 572 浏览 8 评论 0原文

#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;
}

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

#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;
}

Follow up question: How to I make this type safe? That is, If someone forgets to implement method2, I would like the compiler to catch it. I don't want this to blow up at runtime.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

陌若浮生 2024-10-19 05:56:35

我认为这是有效的原因是,如果您实例化此代码:

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

其中 Derived 没有 method2() 的实现本质上将是一个美化的自递归调用。这里的原因是,在Derived1中,确实有一个名为method2的成员函数,即从基类继承的函数。

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

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

I think the reason that this is valid is that if you instantiate this code:

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

where Derived does not have an implementation of method2() will essentially be a glorified self-recursive call. The reason here is that in Derived1, there is indeed a member function called method2, namely the one inherited from the base class.

I tried running this code, and sure enough the call to method2 caused a stack overflow from self-recursion.

Normally, the CRTP avoids this by not having the base class function call a derived class function of the same name. That way, if the derived class is missing a particular function, the call triggers a compiler error. In your case, this doesn't happen because the function itself could be referenced indirectly from the base class.

面犯桃花 2024-10-19 05:56:35
  Derived1 d1;
  d1.method2();

尽管 Derived1 没有定义 method2(),但它还是通过继承 Base 来获取它。这就是它编译和运行的原因。 d1.method2() 实际上调用了 Base::method2(),后者又调用了自身。这是一个递归调用。

  Derived1 d1;
  d1.method2();

Even though Derived1 doesn't define method2(), it gets it by inheriting Base anyway. That is why it compiles and runs. d1.method2() actually calls Base::method2(), which again calls itself. It's a recursive call.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文