logo

Plantillas en C++ con ejemplos

A plantilla es una herramienta simple pero muy poderosa en C++. La idea simple es pasar el tipo de datos como parámetro para que no necesitemos escribir el mismo código para diferentes tipos de datos. Por ejemplo, es posible que una empresa de software necesite ordenar() para diferentes tipos de datos. En lugar de escribir y mantener varios códigos, podemos escribir un sort() y pasar el tipo de datos como parámetro.

C++ agrega dos nuevas palabras clave para admitir plantillas: 'plantilla' y 'escribe un nombre' . La segunda palabra clave siempre se puede sustituir por la palabra clave 'clase' .



¿Cómo funcionan las plantillas?

Las plantillas se expanden en el momento del compilador. Esto es como las macros. La diferencia es que el compilador realiza una verificación de tipos antes de la expansión de la plantilla. La idea es simple, el código fuente contiene solo función/clase, pero el código compilado puede contener múltiples copias de la misma función/clase.

plantillas-cpp

Plantillas de funciones

Escribimos una función genérica que se puede utilizar para diferentes tipos de datos. Ejemplos de plantillas de funciones son sort(), max(), min(), printArray().

Para saber más sobre el tema consulte Genéricos en C++ .



Ejemplo:

C++
// C++ Program to demonstrate // Use of template #include  using namespace std; // One function works for all data types. This would work // even for user defined types if operator '>' es una plantilla sobrecargadaT myMax(T x, T y) { return (x> y)? x : y; } int main() { // Llama a myMax para int cout<< myMax (3, 7)<< endl;  // call myMax for double  cout << myMax(3.0, 7.0)<< endl;  // call myMax for char  cout << myMax('g', 'e')<< endl;  return 0; }>

Producción
7 7 g>

Ejemplo: Implementar Ordenamiento de burbuja usando plantillas en C++

C++
// C++ Program to implement // Bubble sort // using template function #include  using namespace std; // A template function to implement bubble sort. // We can use this for any data type that supports // comparison operator  template void bubbleSort(T a[], int n) { for (int i = 0; i< n - 1; i++)  for (int j = n - 1; i < j; j--)  if (a[j] < a[j - 1])  swap(a[j], a[j - 1]); } // Driver Code int main() {  int a[5] = { 10, 50, 30, 40, 20 };  int n = sizeof(a) / sizeof(a[0]);  // calls template function  bubbleSort (un);  corte<< ' Sorted array : ';  for (int i = 0; i < n; i++)  cout << a[i] << ' ';  cout << endl;  return 0; }>

Producción
 Sorted array : 10 20 30 40 50>

Plantillas de clase

Las plantillas de clase, como las plantillas de funciones y las plantillas de clase, son útiles cuando una clase define algo que es independiente del tipo de datos. Puede ser útil para clases como LinkedList, BinaryTree, Stack, Queue, Array, etc.



Ejemplo:

C++
// C++ Program to implement // template Array class #include  using namespace std; template clase Matriz { privado: T* ptr;  tamaño entero; público: Matriz(T arr[], int s);  impresión nula(); }; plantillaFormación::Array(T arr[], int s) { ptr = nuevo T[s];  tamaño = s;  para (int i = 0; i< size; i++)  ptr[i] = arr[i]; } template matriz vacía::imprimir() { para (int i = 0; i< size; i++)  cout << ' ' << *(ptr + i);  cout << endl; } int main() {  int arr[5] = { 1, 2, 3, 4, 5 };  Array a(arreglo, 5);  una impresión();  devolver 0; }>

Producción
 1 2 3 4 5>

¿Puede haber más de un argumento a favor de las plantillas?

Sí, al igual que los parámetros normales, podemos pasar más de un tipo de datos como argumentos a las plantillas. El siguiente ejemplo demuestra lo mismo.

Ejemplo:

C++
// C++ Program to implement // Use of template #include  using namespace std; template clase A { T x;  Uy; público: A() { cout<< 'Constructor Called' << endl; } }; int main() {  Aa;  A b;  devolver 0; }>

Producción
Constructor Called Constructor Called>

¿Podemos especificar un valor predeterminado para los argumentos de la plantilla?

Sí, al igual que los parámetros normales, podemos especificar argumentos predeterminados para las plantillas. El siguiente ejemplo demuestra lo mismo.

Ejemplo:

C++
// C++ Program to implement // Use of template #include  using namespace std; template clase A { público: T x;  U y;  A() { cout<< 'Constructor Called' << endl; } }; int main() {  // This will call A  Aa;  devolver 0; }>

Producción
Constructor Called>

¿Cuál es la diferencia entre sobrecarga de funciones y plantillas?

Tanto la sobrecarga de funciones como las plantillas son ejemplos de características de polimorfismo de la programación orientada a objetos. La sobrecarga de funciones se utiliza cuando varias funciones realizan operaciones bastante similares (no idénticas), y las plantillas se utilizan cuando varias funciones realizan operaciones idénticas.

¿Qué sucede cuando hay un miembro estático en una clase/función de plantilla?

Cada instancia de una plantilla contiene su propia variable estática. Ver Plantillas y variables estáticas para más detalles.

¿Qué es la especialización de plantillas?

La especialización de plantillas nos permite tener diferentes códigos para un tipo de datos en particular. Ver Especialización de plantillas para más detalles.

¿Podemos pasar parámetros que no sean de tipo a las plantillas?

Podemos pasar argumentos que no sean de tipo a las plantillas. Los parámetros que no son de tipo se utilizan principalmente para especificar valores máximos o mínimos o cualquier otro valor constante para una instancia particular de una plantilla. Lo importante a tener en cuenta sobre los parámetros que no son de tipo es que deben ser constantes. El compilador debe conocer el valor de los parámetros que no son de tipo en el momento de la compilación. Porque el compilador necesita crear funciones/clases para un valor que no sea de tipo específico en el momento de la compilación. En el siguiente programa, si reemplazamos 10000 o 25 con una variable, obtenemos un error del compilador.

¿Qué es un personaje especial?

Ejemplo:

C++
// C++ program to demonstrate // working of non-type parameters // to templates in C++ #include  using namespace std; template int arrMin(T arr[], int n) { int m = máx;  para (int i = 0; i< n; i++)  if (arr[i] < m)  m = arr[i];  return m; } int main() {  int arr1[] = { 10, 20, 15, 12 };  int n1 = sizeof(arr1) / sizeof(arr1[0]);  char arr2[] = { 1, 2, 3 };  int n2 = sizeof(arr2) / sizeof(arr2[0]);  // Second template parameter  // to arrMin must be a  // constant  cout << arrMin (arr1, n1)<< endl;  cout << arrMin(arr2, n2);    devolver 0; }>

Producción
10 1>

A continuación se muestra un ejemplo de un programa C++ para mostrar diferentes tipos de datos utilizando un constructor y una plantilla. Realizaremos algunas acciones.

  • pasar el valor del carácter creando un objeto en la función main().
  • pasar un valor entero creando un objeto en la función main().
  • pasando un valor flotante creando un objeto en la función main().

Ejemplo:

C++
// C++ program to show different data types using a // constructor and template. #include  using namespace std; // defining a class template template información de clase { public: // constructor de tipo plantilla info(T A) { cout<< '
'  << 'A = ' << A  << ' size of data in bytes:' << sizeof(A);  }  // end of info() }; // end of class // Main Function int main() {  // clrscr();  // passing character value by creating an objects  infop('x');  // pasando un valor entero creando una información de objeto q(22);  // pasando valor flotante creando una información de objetor(2,25);  devolver 0; }>

Producción
A = x size of data in bytes:1 A = 22 size of data in bytes:4 A = 2.25 size of data in bytes:4>

Deducción del argumento de la plantilla

La deducción de argumentos de plantilla deduce automáticamente el tipo de datos del argumento pasado a las plantillas de clase o función. Esto nos permite crear una instancia de la plantilla sin especificar explícitamente el tipo de datos.

Por ejemplo, considere la siguiente plantilla de función para multiplicar dos números:

template  t multiply (t num1,t num2) { return num1*num2; }>

En general, cuando queremos usar la función multiplicar() para números enteros, tenemos que llamarla así:

multiply (25, 5);>

Pero también podemos llamarlo:

multiply(23, 5);>

No especificamos explícitamente el tipo, es decir, 1,3 son números enteros.

Lo mismo ocurre con las clases de plantilla (solo desde C++ 17). Supongamos que definimos la clase de plantilla como:

template class student{  private:  t total_marks;  public:  student(t x) : total_marks(x) {} };>

Si queremos crear una instancia de esta clase, podemos usar cualquiera de las siguientes sintaxis:

student stu1(23);    or  student stu2(24);>

Nota: Es importante tener en cuenta que la deducción de argumentos de plantilla para clases solo está disponible desde C++ 17, por lo que si intentamos utilizar la deducción automática de argumentos de plantilla para una clase en una versión anterior, arrojará un error.

atajos de teclado de Linux

Ejemplo de deducción de argumento de plantilla

El siguiente ejemplo demuestra cómo la plantilla de clase vectorial STL deduce el tipo de datos sin especificarlo explícitamente.

C++
// C++ Program to illustrate template arguments deduction in // STL #include  #include  using namespace std; int main() {  // creating a vector object without specifying  // type  vector v1{ 1.1, 2.0, 3.9, 4.909 };  cout << 'Elements of v1 : ';  for (auto i : v1) {  cout << i << ' ';  }  // creating a vector object without specifying type  vector v2{ 1, 2, 3, 4 };  cout << endl << 'Elements of v2 : ';  for (auto i : v2) {  cout << i << ' ';  } }>


Producción

Elements of v1 : 1.1 2 3.9 4.909  Elements of v2 : 1 2 3 4>

Nota: El programa anterior fallará en la compilación en C++ 14 y en compiladores inferiores ya que la deducción de argumentos de plantilla de clase se agregó en C++ 17.

Deducción de argumentos de plantilla de función

La deducción de argumentos de plantillas de funciones ha sido parte de C++ desde el estándar C++98. Podemos omitir la declaración del tipo de argumentos que queremos pasar a la plantilla de función y el compilador deducirá automáticamente el tipo utilizando los argumentos que pasamos en la llamada a la función.

Ejemplo: En el siguiente ejemplo, demostramos cómo las funciones en C++ deducen automáticamente su tipo por sí mismas.

C++
// C++ program to illustrate the function template argument // deduction #include  using namespace std; // defining function template template t multiplicar(t primero, t segundo) { return primero * segundo; } // código del controlador int main() { resultado automático = multiplicar(10, 20);  std::cout<< 'Multiplication OF 10 and 20: ' << result  << std::endl;  return 0; }>

Producción
Multiplication OF 10 and 20: 200>

Nota: Para las plantillas de funciones que tienen el mismo tipo para los argumentos como template void function(t a1, t a2){}, no podemos pasar argumentos de diferentes tipos.

Deducción de argumentos de plantilla de clase (C++17 en adelante)

La deducción del argumento de la plantilla de clase se agregó en C++ 17 y desde entonces ha sido parte del lenguaje. Nos permite crear instancias de plantilla de clase sin definir explícitamente los tipos, al igual que las plantillas de funciones.

Ejemplo: En el siguiente ejemplo, demostramos cómo el compilador clasifica automáticamente las plantillas en C++.

C++
// C++ Program to implement Class Template Arguments // Deduction #include  #include  #include  using namespace std; // Defining class template template estudiante de clase {privado: cadena nombre_estudiante;  T total_marcas; public: // Constructor parametrizado estudiante(cadena n, T m): nombre_estudiante(n), marcas_total(m) { } void getinfo() { // imprimiendo los detalles del cout del estudiante<< 'STUDENT NAME: ' << student_name << endl;  cout << 'TOTAL MARKS: ' << total_marks << endl;  cout << 'Type ID: ' << typeid(total_marks).name()  << endl;  } }; int main() {  student s1('Vipul', 100); // Deduces student  student s2('Yash', 98.5); // Deduces student  s1.getinfo();  s2.getinfo();  return 0; }>


Producción

STUDENT NAME: Vipul TOTAL MARKS: 100 Type ID: i STUDENT NAME: Yash TOTAL MARKS: 98.5 Type ID: d>

Aquí, i significa int y d significa doble.

Para metaprogramación de plantillas, r Consulte el siguiente artículo: Metaprogramación de plantillas .

Tomar un Prueba sobre plantillas . Java también admite estas funciones. Java lo llama genéricos .