2011-04-04 107 views
6

这里访问是(简化的)基类:C++:与CRTP,在派生类定义的类不是基础类

template <class T> 
class SharedObject 
{ 
protected: 
    QExplicitlySharedDataPointer <typename T::Data> d; 
}; 

这里是衍生自:

class ThisWontCompile : public SharedObject <ThisWontCompile> 
{ 
private: 
    friend class SharedObject; 
    struct Data : public QSharedData 
    { 
     int id; 
    }; 
}; 

是否有任何解决方法来访问ThisWontCompile :: Data from SharedObject?从基础对象派生的对象究竟能够做什么和不能做什么?

回答

12

这实际上与可访问性和友谊无关,它与使用CRTP有关。请考虑以下的例子,还显示出该问题:

template <class T> 
struct Base 
{ 
    typedef typename T::Data Data; 
}; 

struct ThisWontCompile : public Base<ThisWontCompile> 
{ 
    struct Data { }; 
}; 

的问题是,ThisWontCompile是在它被用作模板参数Base的时间不完全的,所以它只能被用作Base一个不完整的类型。

对于您的具体问题的解决方案了一把,咨询解答this other question,尤其是马丁的建议,使用traits类,这基本上是这样的:

// Base 
template <typename T> 
struct BaseTraits; 

template <typename T> 
struct Base 
{ 
    typedef typename BaseTraits<T>::Data Data; 
}; 

// Derived 
struct Derived; 

template <> 
struct BaseTraits<Derived> 
{ 
    struct Data { }; 
}; 

struct Derived : public Base<Derived> 
{ 
}; 

typename BaseTraits<Derived>::Data可以在两个Derived使用并在Base。如果Derived本身就是一个模板,那么可以对特征类使用部分特化。

+0

因此,我根本无法访问任何派生类成员? – Septagram 2011-04-04 05:17:57

+0

@Stagram:不直接,不。如果该解决方案适用于您的特定场景,我会考虑链接答案中的特质类解决方案。 – 2011-04-04 05:21:48

+2

@Stagram:如果你陈述你实际需要解决的问题,我们可能会在那里提供帮助。至于你的特定问题,你可以访问CRTP模板中的实例化类的成员,只要你强制转换,并且这些成员的使用不会影响类型的内存布局(即不能使用'static const int '在实例化类型中设置CRTP类中数组的大小)。我认为这个特性被现代C++设计中的Alexandrescu用于基于策略的C++类层次设计。 – 2011-04-04 08:03:37