派生类的 C++ CRTP 构造函数

标签 c++ constructor crtp

我对 CRTP 有一些疑问。假设我有以下代码

#include <iostream>

// interface

template<class Imp>
class Interface{
  public:
    inline void print(void){
      std::cout<<"value: ";
      return asImp().print();
    }
  private:
    typedef Imp Implementation;
    inline Implementation& asImp(void){return static_cast<Implementation&>(*this);}
};

// add
class Add:public Interface<Add>{
  public:
    inline void print(void){std::cout<<value<<std::endl;++value;}
  private:
    int value;
};

// main
int main(void){
  Interface<Add> foo;
  foo.print();
  foo.print();
}

输出是

value: 0
value: 1

因此,变量 value 似乎被默认构造函数构造为 0。但是我不明白这个构造函数是在何时何地被调用的,因为没有创建派生类的对象。

此外,假设我想用不同的起始值创造值(value),我如何使用这种设计模式来实现? 显然,我可以在派生类中创建一个 init() 方法,该方法在基类的构造函数中调用,但它不适用于没有默认构造函数的类型。

最后,是否可以将传递给基类构造函数的一些参数转发给派生类的构造函数?

最佳答案

在您的源代码中,您自己将基类命名为Interface。在面向对象的意义上,您创建的不是 Interface 的实例,而是从 Interface 派生的类的实例。您在 main 中的代码错误地实例化了一个 Interface 而不是从它派生的类。您可以通过强制 Interface 具有使其无法实例化的属性来解决此问题。例如:

template<class Imp>
class Interface {
    //...
protected:
    Interface () {} // not accessible except by derived
};

与常规多态性不同,您并不是真的希望传递 Interface 对象。 Interface 通过提供预期的方法来强制执行特定接口(interface),而那些从 Interface 派生的方法必须采用该接口(interface)的预期。您的示例有点做作,因为 Interface 实际上只是分派(dispatch)到派生中的相同命名方法。但是,一个更好的例子是 Interface 使用它期望派生类型提供的属性来提供实现。

在下面的例子中,我们看到Worker继承了WorkerInterface的接口(interface)。但是,由于WorkerInterface的期望,需要实现perform()wait()。纯接口(interface)通过纯虚方法强制执行此要求,而 CRTP 通过模板扩展强制执行此要求。

template <typename JOB>
class WorkerInterface {
public:
    void work () { while (job().wait()) job().perform(); }
private:
    JOB & job () { return *static_cast<JOB *>(this); }
protected:
    WorkerInterface () {}
};

class Worker : public WorkerInterface<Worker>
{
    friend class WorkerInterface<Worker>;
    int state_;
    void perform () { std::cout << "Worker: " << __func__ << '\n'; }
    bool wait () { return state_--; }
public:
    Worker () : state_(1) {}
};

int main ()
{
    Worker w;
    w.work();
}

现在,任何派生自 WorkerInterface 的类都将提供一个 work() 方法,只要派生类提供合适的实现,该方法就会做“正确”的事情wait()perform() 的组合。

关于派生类的 C++ CRTP 构造函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25083574/

相关文章:

c++ - 如何在 Objective-C 中验证 JSON Schema?

c++ - 在 C 中嵌入 XUL 后端

java - Android:无法实例化类:没有空构造函数

c++ - 哪个指针赋值更好(C++)

c++ - 带有 CRTP 的转发构造函数

c++ - 递归模板成语如何避免基类是子类的 friend

c++ - opengl Framebuffer offscreen 到纹理,颜色错误

c# - 将结构从 C++ 转换为 C#

c# 发出动态方法委托(delegate)以加载参数化构造函数问题

c++ - 在执行 SFINAE 时访问模板化派生类 (CRTP) 的静态函数时类型不完整