2011-04-04 19 views
6

Aquí está el (simplificado) clase base:C++: Con CRTP, clase definida en la clase derivada no es accesible en la clase base

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

Y aquí es la deriva:

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

¿Hay alguna solución alternativa para acceder al ThisWontCompile :: Data desde SharedObject? ¿Qué es exactamente lo que se puede y no se puede hacer con el objeto derivado del objeto base?

Respuesta

12

Esto en realidad no está relacionado con la accesibilidad y la amistad, está relacionado con el uso de CRTP. Considere el ejemplo siguiente, que también presenta el problema:

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

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

El problema es que ThisWontCompile es incompleta en el momento que se utiliza como un argumento de plantilla para Base, por lo que sólo se puede utilizar como un tipo incompleto en Base.

Por un puñado de soluciones a su problema específico, consultar las respuestas a this other question, especialmente la recomendación de Martin utilizar una clase rasgos, lo que básicamente el siguiente aspecto:

// 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 se puede utilizar tanto en Derived y en Base. Si Derived es una plantilla, puede usar una especialización parcial para la clase de rasgos.

+0

Entonces, ¿no puedo acceder a ningún miembro derivado de la clase? – Septagram

+0

@Septagram: No directamente, no. Consideraría la solución de clase de rasgos en la respuesta vinculada, si esa solución funciona para su escenario específico. –

+2

@Septagram: si declara lo que realmente necesita resolver, podríamos ayudarlo allí. A partir de su pregunta en particular, puede acceder a los miembros de la clase de creación de instancias en la plantilla CRTP siempre que fuerce un reparto, y que el uso de esos miembros no afecte el diseño de la memoria del tipo (es decir, no puede usar 'static const int 'en el tipo de creación de instancias para establecer el tamaño de una matriz en la clase CRTP). Creo que esa característica es utilizada por Alexandrescu en Modern C++ Design en el diseño basado en políticas de jerarquías de clases C++. –

Cuestiones relacionadas