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

时间:2014-08-01 15:25:36

标签: 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。但我不明白这个构造函数的调用位置和时间,因为没有创建派生类的对象。

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

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

2 个答案:

答案 0 :(得分:2)

您实际上创建派生对象。

您正在创建基类对象并将其转换为派生类型的引用,但基础对象仍然是基类,因此它的错误

static_cast总是成功,但是如果你没有强制转换为正确的类型会引发未定义的行为,而dynamic_cast如果你输入错误则会返回NULL指针。

- &GT;在这里试一试,你可能会或可能不会得到垃圾值:http://ideone.com/dP3jjU

一旦你解决了上述问题,另一个初始化问题应该是直截了当的。

更多相关信息:Should static_cast<Derived *>(Base pointer) give compile time error?

答案 1 :(得分:1)

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

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

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

在下面的示例中,我们看到Worker继承了WorkerInterface的界面。但是,由于WorkerInterface的期望,需要实施perform()wait()。虽然纯接口使用纯虚方法强制执行此要求,但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()方法,该方法将执行“正确”的操作。 {1}}。