使用 CRTP 时如何调用派生 class 的构造函数?

How can I call the constructor of the derived class when using CRTP?

我有以下设置:

#include <iostream>
template <typename T>
struct feline {
  void roar() noexcept {
      static_cast<T*>(this)->do_roar();
  }
      feline() noexcept {
      std::cerr << "Feline ctor" << std::endl;
  }
};

struct lion : public feline<lion> {
  lion() noexcept : feline() {
    std::cerr << "Lion ctor" << std::endl;
  }
  void do_roar() noexcept {
      std::cerr << "Lion roar" << std::endl;
  }
};

struct tiger : public feline<tiger> {
  tiger() noexcept : feline() {
    std::cerr << "Tiger ctor" << std::endl;
  }
  void do_roar() noexcept {
      std::cerr << "Tiger roar" << std::endl;
  }
};

int main()
{
    feline<lion> lion;
    lion.roar();
    feline<tiger> tiger;
    tiger.roar();
}

当我执行它时,我得到以下结果:

Feline ctor
Lion roar
Feline ctor
Tiger roar

这意味着永远不会调用 Lion 和 Tiger 的构造函数。我怎样才能做到这一点?

您使用的 CRTP 有点错误。暂时忘记基础 class 是在继承 class 上参数化的事实,然后你所做的是这样的:

struct feline { };
struct lion : feline {};

feline roary;        // in your actual code this is parametrized with lion
                     // but still it is no lion !

当你真正想要创造一只狮子时:

lion roary;          // this is a lion !

因为你从来没有创造过真正的狮子。

CRTP 需要实际 class 的对象才能正常工作。

请记住,基础 class 永远不会直接实例化子 class,因为这都是为了强制 class 支持某些功能,而不是 class 逻辑继承。

您的代码可能会崩溃,但它不会,这是因为函数 do_roar 不访问任何私有变量。尝试将一些成员添加到 lion 并在 do_roar 中使用它们,您会看到...

如果您想要狮子,请使用 lion class,feline<lion> 只是 feline<T> 的实例,其中 T = lion.

您声明了新的 类 但没有使用它们。

以下是使用您的新 类:

修改后的 main()
int main()
{
    lion l;
    l.roar();
    tiger t;
    t.roar();
}

输出:

Feline ctor
Lion ctor
Lion roar
Feline ctor
Tiger ctor
Tiger roar