Pregunta

¿Cuáles son algunos usos prácticos de la " Patrón de plantilla curiosamente recurrente " ;? La " clase contada " El ejemplo que se muestra comúnmente no es un ejemplo convincente para mí.

¿Fue útil?

Solución

Enlace dinámico simulado . Evitar el costo de las llamadas a funciones virtuales y conservar algunos de los beneficios jerárquicos es una enorme ganancia para los subsistemas donde se puede realizar en el proyecto en el que estoy trabajando actualmente.

Otros consejos

También es especialmente útil para mixins (me refiero a las clases que hereda para proporcionar funcionalidad) que necesitan saber qué tipo están operando (y, por lo tanto, necesitan ser plantillas).

En Effective C ++ , Scott Meyers proporciona como ejemplo una plantilla de clase NewHandlerSupport < T > ;. Este contiene un método estático para anular el nuevo controlador para una clase particular (de la misma manera que std :: set_new_handler hace para el operador predeterminado nuevo), y un operador nuevo que usa el controlador. Para proporcionar un controlador por tipo, la clase padre necesita saber en qué tipo está actuando, por lo que debe ser una plantilla de clase. El parámetro de la plantilla es la clase secundaria.

Realmente no podría hacer esto sin CRTP, ya que necesita que se cree una instancia de la plantilla NewHandlerSupport por separado, con un miembro de datos estáticos separado para almacenar el new_handler actual, por clase que lo use.

Obviamente, todo el ejemplo no es seguro para subprocesos, pero ilustra el punto.

Meyers sugiere que el CRTP podría considerarse como "Hazlo por mí". Yo diría que este es generalmente el caso de cualquier mezcla, y el CRTP se aplica en el caso de que necesite una plantilla de mezcla en lugar de solo una clase de mezcla.

El CRTP se vuelve mucho menos curioso si considera que el tipo de subclase que se pasa a la superclase solo es necesario al momento de la expansión del método. Entonces se definen todos los tipos. Solo necesita el patrón para importar el tipo de subclase simbólico a la superclase, pero es solo una declaración hacia adelante, ya que todos los tipos de parámetros de plantillas formales son por definición, en lo que respecta a la superclase.

Usamos en una forma algo modificada, pasando la subclase en una estructura de tipo de rasgos a la superclase para hacer posible que la superclase devuelva objetos del tipo derivado. La aplicación es una biblioteca para el cálculo geométrico (puntos, vectores, líneas, cuadros) donde toda la funcionalidad genérica se implementa en la superclase, y la subclase solo define un tipo específico: CFltPoint hereda de TGenPoint. Además, CFltPoint existía antes de TGenPoint, por lo que la subclasificación era una forma natural de refactorizar esto.

Por lo general, se usa para patrones de tipo polimórfico en los que no es necesario poder elegir la clase derivada en tiempo de ejecución, solo en tiempo de compilación. Esto puede ahorrar la sobrecarga de la llamada a la función virtual en tiempo de ejecución.

Para un uso de CRTP en una biblioteca del mundo real, consulte ATL y WTL (wtl.sf.net). Se usa ampliamente allí para el polimorfismo en tiempo de compilación.

Se siente como una macro de C: aproveche que la macro no se compila en el momento de la definición, sino en el momento de su uso.

#define CALL_THE_RIGHT_FOO foo()

archivo A:

static void foo() {
   // do file A thing
}
...
CALL_THE_RIGHT_FOO
...

archivo A:

static void foo() {
   // do file B thing
}
...
CALL_THE_RIGHT_FOO
...

El patrón de uso de la plantilla que estás describiendo nos permite hacer lo que llamamos " foo right " en la plantilla principal, posponer la definición de lo que es exactamente el derecho correcto hasta que se cree una instancia de la plantilla. Excepto en este caso, es la distinción entre ClassA :: foo y ClassB :: foo según el valor de T en Parent.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top