使用CRTP时,如何调用派生类的构造函数

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

本文关键字:调用 派生 构造函数 CRTP 何调用 使用      更新时间:2023-10-16

我有以下设置:

#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

这意味着狮子和老虎的构造源从未被调用。我该如何实现?

因为您永远不会创建实际的狮子。

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

请记住,基类永远不会直接实例化儿童班,因为这一切都涉及迫使该类支持某些功能而不是经典的继承。

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

如果您想要狮子使用lion类,则feline<lion>只是feline<T>的实例化,其中T = lion

您使用的是CRTP略有错误。片刻,忘记了基类是在继承类中参数化的事实,那么您的工作就是:

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 !

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

以下是使用新类的修订main()

int main()
{
    lion l;
    l.roar();
    tiger t;
    t.roar();
}

输出:

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