2011-12-01 19 views
7

Durante la lectura de un artículo, me encontré con la siguiente sintaxis:¿Cómo puede heredar una clase de una plantilla basada en sí misma?

template <typename T> 
class MyTemplate 
{ 
    T* member; 
    T* method(); 
    // ... 
} 

class MyClass : public MyTemplate<MyClass> 
{ 
    // ... 
} 

No entiendo exactamente cómo MyClass puede heredar de una plantilla que se basa en sí mismo. ¿Podría explicarme cómo funciona esto?

Respuesta

8

Esto se llama Curiously Recurring Template Pattern, o CRTP para abreviar. Se utiliza para lograr el efecto del polimorfismo estático al aprovechar el hecho de que cuando llega al MyTemplate<MyClass> en la línea class MyClass : public MyTemplate<MyClass>, MyClass está semidefinido (es un tipo incompleto) por lo que puede almacenar punteros a ese tipo, etc., y hacer cosas con él que no requieren un tipo completo.

+0

No diría que 'MyClass' está incompleto. Puede ser que desee que se proporcione alguna funcionalidad genérica para esta clase. Por ejemplo [Ejemplo] (http://drdobbs.com/cpp/184403484). –

+1

@ R.K en el punto de 'public MyTemplate ', 'MyClass' es de hecho un tipo incompleto. Significa que puede almacenar punteros y referencias, etc. –

+0

Sí, tiene razón. Ahora que vuelvo a leer tu descripción, es correcta. Pensé que querías decir que MyClass es, por ejemplo, un tipo incompleto. –

2

¿Podría explicarnos cómo funciona esto?

Uhm ... it just .. does? El estándar permite específicamente que los parámetros de la plantilla sean de tipo incompleto. Y dado que ningún método en la clase base CRTP necesita un tipo completamente definido, todo está bien.

§3.9.2 p3 [basic.compound] se les permite
punteros a tipos incompletas aunque hay restricciones en lo que se puede hacer con ellos (3.11).

§14.3.1 p2 [temp.arg.tipo]
[Nota: un argumento de tipo de plantilla puede ser un tipo incompleto (3.9). -finalizar nota]

2

Esto se llama CRTP. Se utiliza para el polimorfismo estático que puede ser más rápido que el uso de virtual.

: public MyTemplate<MyClass> 

Crea una instancia MyTemplate<MyClass>, aunque desde MiClase está incompleto sólo se puede usar T de maneras que no requieren un tipo completo. Como usar un puntero o llamar a una función miembro.

De todos modos, basta con ver el fragmento, que es esencialmente el mismo que esto:

class MyClass 
{ 
    MyClass* member; 
    MyClass* method(); 
} 

que es perfectamente legal y comprensible.

Cuestiones relacionadas