Plantillas en c ++

C ++ es un ejemplo de un lenguaje de programación fuertemente tipado. Es este fuerte-ness escrito que permite a las funciones a ser sobrecargados, como se muestra en el siguiente fragmento de código:

void grado (Estudiantes) grado -void (Land) fn -void (Estudiante s) {grado (s) -}

C ++ no tiene problemas para entender que la llamada a grado (s) debe dirigirse a la función grado (Estudiante).

Métodos fuerzas mecanografía fuerte para ser sobrecargados que aparece el mismo en el nivel C ++, pero son muy diferentes en su aplicación como en el siguiente ejemplo:

int compare (int l, int r) {return (l> r)? 1: (l lt; r)? -1: 0-} int comparar (l doble, doble r) {return (l> r)? 1: (l lt; r)? -1: 0-}

Esta compare () devuelve un 1 si la izquierda; argumento mano es mayor que el derecho, lado, un -1 si la izquierda; argumento mano es inferior a la derecha; la mano, y un 0 si son iguales. A pesar de la similitud del código fuente, el código de máquina generado por estas dos funciones es muy diferente, debido a diferencias en la forma en que int se implementa frente doble a pie de máquina.

El preprocesador ofrece una manera de evitar este tipo de implementaciones redundantes:

#define Comparar (l, r) (((l)> (r)) 1:?? ((l) lt; (r)) -1: 0)

Sin embargo, este adolece de una serie de graves limitaciones - no menos importante de los cuales es la necesidad de que la función de encajar en una expresión (en efecto, en una línea). Además, los errores en una macro preprocesador pueden conducir a problemas que son difíciles de depurar.

Plantillas de función

La función de plantilla en C ++ permite al programador para conservar las ventajas de tipado fuerte y evitar las limitaciones del preprocesador mediante el uso de un marcador de posición para el tipo. A continuación se definen compare () por alguna clase no especificada T a ser nombrado más tarde:

modelo  T Comparar (T l, T r) {return (l> r)? 1: (l lt; r)? -1: 0-}

Tal definición es conocida como una plantilla de función. Esta plantilla de función - cuyo nombre completo es comparar(T, T) - se puede convertir en una función real mediante el suministro T:

plantilla de doble comparar(doble, doble) -

También puede permitir que C ++ para encontrar y crear una instancia de la clase T para usted, ya sea proporcionando una declaración parcial o mediante el uso de la función, como se muestra en el siguiente fragmento de código de ejemplo:

plantilla de doble comparar (doble, doble) -INT main () {cout lt; lt; Comparar (0, 0) lt; lt; "" Lt; lt; Comparar (1.0, 2.0) lt; lt; endl retorno 0-}

Aquí la función Comparar (doble, doble) es creado por la declaración inicial, incluso sin el extra después del nombre de la función. La funcion Comparar (int, int) se crea cuando se utiliza en la declaración Comparar (0, 0).

Plantillas de clase

Función de la plantilla El C ++ permite que las clases que se definen utilizando los tipos que se especifican más adelante. Esto resuelve una serie de diferentes problemas de una manera con seguridad de tipos. Uno de los problemas, aunque lejos de ser el único problema, es que de los contenedores genéricos. (LA contenedor es una clase que contiene objetos de otra clase).

En los primeros días de C ++, la única manera de crear una clase de contenedor genérico era confiar en el genérico vacío puntero (el puntero de la clase void *). Al igual que el #define "función" se mencionó anteriormente, este enfoque eludió efectivamente sólido mecanismo de tipificación C ++ 's con declaraciones como la siguiente:

clase Container {public: void add (void *) - void * get () - // ... otros miembros ...} - Clase storeStudent contenedor vacío (Estudiante s) {contenedor.add ((void *) s) -} Estudiante * getStudent () {return (Estudiante *) container.get () -}

Plantillas de C ++ permiten al programador definir una plantilla de clase en el que no se especifica uno o más tipos hasta que se utiliza la clase:

modelo  clase Container {public: void put (T * p) -T * get () -} -

En la práctica, la plantilla de clase primero se debe convertir en una clase real, mediante el suministro de un tipo de T. Puede ser utilizada en condiciones de seguridad de tipo completo:

Recipiente contenedores-Estudiante s-container.put (s) -Estudiante * pS = container.get () -

No hay necesidad de definir su propio contenedor de clase de la Biblioteca de plantillas estándar proporciona una serie de tales clases. Por ejemplo, el siguiente fragmento de código crea una lista enlazada de punteros a Estudiante objetos y agrega una a la final de la lista:

// debe incluir  al inicio del modulelist slist-Estudiante * pS = new Estudiante () - sList.push_back (s) -

Muchas de las clases que se utiliza todos los días son, de hecho, las instancias de plantillas de clase. El ejemplo más común es cuando istream y ostream se utilizan para la entrada y salida estándar.

Iteradores

Aunque no son directamente parte de la función de plantilla, iteradores proporcionar una manera estándar de acceder a los diferentes tipos de contenedores disponibles en la Biblioteca de plantillas estándar. Todos los contenedores proporcionan un método que devuelve un iterador al principio del contenedor y una manera de comprobar si el iterador está en el extremo del recipiente (esto incluye los contenedores no ordenadas para el que 'principio' y 'final' es un concepto aleatorio). El iterador sí ofrece al menos dos métodos: una para devolver el objeto actual y uno para evitar el iterador al siguiente objeto.

El código siguiente itera a través de una colección de punteros a Estudiante objetos. Este mismo código funciona independientemente de que uno de los muchos tipos de envases a los que decide utilizar:

// DisplayAllStudents - iterar a través de una lista de // Estudiantes- invocar el toString () // método sobre displayAllStudents eachvoid (lista slist) {for (iter auto = sList.begin (!) - iter = sList.end () - iter ++) {Estudiante * pS = * iter-cout lt; lt; PS-> toString () lt; lt; endl-}}

(Este ejemplo asume que la clase Estudiante incluye un método Encadenar() que devuelve una representación de caracteres de un estudiante.)

Esta función utiliza el comenzar() método para volver un iterador que apunta al primer miembro del recipiente. Las iteraciones de la función a través del contenedor hasta que los puntos de iterador a fin() que se refiere al miembro después del último miembro contenedor. El operador de incremento mueve el iterador al siguiente miembro en el contenedor mientras que el operador * devuelve el objeto apuntado por el iterador.

los auto palabra clave dice declarar iter al ser del tipo devuelto por sList.begin (). Esta es una extensión de C ++ añadido por la norma 2.011. Sin auto, Me hubiera declarado iter a ser de tipo Lista ::const_iterador.