0

在我的一个项目中,我使用与enable_crtp答案 1 中相同的 CRTP 方法(源自 ):如何将模板参数传递给 CRTP?

但是我也需要从派生类派生。有什么方法可以使这项工作不回退到仅 static_cast this 指针而是使用 Enable CRTP 基类中的 self() 方法?

#include "EnableCRTP.h"

template<typename DERIVED>
class BASE : public EnableCRTP<DERIVED>
{
    friend DERIVED;
public:
    void startChain()
    {
        self()->chain();
    }
};

template<typename DERIVED>
class Derived1 : public BASE<Derived1<DERIVED> >
{
public:
    void chain()
    {
        std::cout << "Derived1" << std::endl;

        //self()->chain2(); <- compile Error
        static_cast<DERIVED*>(this)->chain2(); // <-Works
    }
};

class Derived2 : public Derived1<Derived2>
{
public:
    void chain2()
    {
        std::cout << "Derived2" << std::endl;
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    Derived2 der;    
    der.startChain();    
    return 0;
}
4

2 回答 2

1

您可以将派生最多的类作为模板参数提供给 CRTP 基类,以便它可以访问其所有成员。代替

template<typename DERIVED>
class Derived1 : public BASE<Derived1<DERIVED> >

采用:

template<typename DERIVED>
class Derived1 : public BASE<DERIVED>

您的代码还有其他问题。例如,您不能self()像以前那样直接调用,因为编译器不知道它self是基类的成员(依赖于模板参数)。相反,调用this->self(). 请参阅此常见问题解答条目

于 2012-11-19T12:30:02.180 回答
0

要做你想做的事,你只需要通过 CRTP 传递最派生的类。在这种情况下,您需要将 Derived1 的定义更改为以下内容:

template<typename DERIVED>
class Derived1 : public BASE< DERIVED >
{
public:
    void chain()
    {
        std::cout << "Derived1" << std::endl;

        this->self()->chain2(); // should work now
        //static_cast<DERIVED*>(this)->chain2(); // <-Works
    }
};

此外,当将 CRTP 与类层次结构一起使用时,通常最好设置层次结构,以便类被设计为派生自(因此是通过 DERIVED 类传递的模板),或者是层次结构的叶子,并且不是来源于。这些叶类根本不必是模板。

于 2012-11-19T12:30:13.970 回答