Plantilla de función [C ++]

  • Otras ideas de programación C ++ llamadas técnicas de programación genéricas  , la principal ventaja es la plantilla

  • C ++ proporciona dos mecanismos de plantilla: plantillas de funciones y plantillas de clases.

1 Sintaxis de la plantilla de función

Función de plantilla de función:

Establecer una función general, el tipo de valor de retorno de la función y el tipo de parámetro formal no se pueden especificar específicamente, representados por un tipo virtual .

gramática:

template<typename T>
函数声明或定义

Explicación:

plantilla --- Declarar para crear una plantilla

typename --- El símbolo detrás de él es un tipo de datos, que puede ser reemplazado por class

T --- Tipo de datos general, el nombre se puede reemplazar, generalmente en letras mayúsculas

#include <iostream>
using namespace std;

//利用模版提供通用的交换函数
template<typename T>
void mySwap(T& a, T&b)
{
	T temp = a;
	a = b;
	b = temp;
}

void test01()
{
	int a = 10;
	int b = 20;
	//利用模板实现交换
	//1、自动类型推导
	mySwap(a, b);

	//2、显示指定类型
	mySwap<int>(a, b);

	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
}

int main(void)
{
	test01();

	system("pause");
	return 0;
}

para resumir:

  • La plantilla de función utiliza la plantilla de palabras clave;

  • Hay dos formas de utilizar las plantillas de funciones: inferencia automática de tipos y visualización de tipos especificados;

  • El propósito de la plantilla es mejorar la reutilización y parametrizar el tipo.

2 Notas sobre las plantillas de funciones

Precauciones:

  • Derivación automática de tipos, debe derivar un tipo de datos coherente T antes de poder usarlo

  • La plantilla debe determinar el tipo de datos de T antes de que pueda usarse

#include <iostream>
using namespace std;

//1 自动类型推导,必须推导出一致的数据类型T,才可以使用
template <typename T>
void mySwap(T& a, T& b)
{
	T temp = a;
	a = b;
	b = temp;
}

void test02()
{
	int a = 10;
	int b = 20;
	char c = 'a';

	mySwap(a, b);
	//mySwap(a, c);   //错误,推导不出一致的T类型

}

// 2、模板必须要确定出T的数据类型,才可以使用
template <typename T>
void func()
{
	cout << "func的调用" << endl;
}

void test002()
{
	//func();          //错误,模板不能独立使用,必须确定出T的类型
	func<int>();       //利用显示指定类型的方式,给T一个类型,才可以使用该模板
}

int main(void)
{
	test02();
	test002();

	system("pause");
	return 0;
}

para resumir:

  • Cuando se usa una plantilla, se debe determinar un tipo de datos común T y se debe deducir un tipo consistente

3 La diferencia entre funciones ordinarias y plantillas de funciones

La diferencia entre funciones ordinarias y plantillas de funciones:

  • La conversión de tipo automática (conversión de tipo implícita) puede ocurrir cuando se llama a una función ordinaria

  • Cuando se llama a la plantilla de función, si se utiliza la inferencia de tipo automática, no se producirá la conversión de tipo implícita

  • Si utiliza la visualización del tipo especificado, puede producirse una conversión de tipo implícita

#include <iostream>
using namespace std;

//普通函数和函数模版的区别
//1、普通函数调用可以发生隐式类型转换
//2、函数模版 用自动类型推导,不可以发生隐式类型转换
//3、函数模版 用显示指定类型,可以发生隐式类型转换

//普通函数
int myAdd04(int a, int b)
{
	return a + b;
}

//函数模版
template<typename T>
T myAdd004(T a, T b)
{
	return a + b;
}


void test04()
{
	int a = 10;
	int b = 20;
	char c = 'a';    //'a' - 97

	//正常调用
	cout << myAdd04(a, b) << endl;
	//隐式转换
	cout << myAdd04(a, c) << endl;

	//函数模版
	cout << myAdd004(a, b) << endl;          //正确
	//cout << myAdd004(a, c) << endl;        //报错,使用自动类型推导时,不会发生隐式类型转换
	cout << myAdd004<int>(a, c) << endl;     //正确,如果用显示指定类型,可以发生隐式类型转换
}


int main4(void)
{
	test04();
	system("pause");
	return 0;
}

Resumen: se recomienda utilizar el método de mostrar el tipo especificado y llamar a la plantilla de función, porque usted mismo puede determinar el tipo general T

4 Reglas de llamada de funciones ordinarias y plantillas de funciones

Las reglas de llamada son las siguientes:

  1. Si se pueden implementar tanto la plantilla de función como la función ordinaria, primero se llama a la función ordinaria

  2. Puede forzar la llamada de una plantilla de función a través de una lista de parámetros de plantilla vacía

  3. Las plantillas de funciones también se pueden sobrecargar

  4. Si la plantilla de función puede producir una mejor coincidencia, llame primero a la plantilla de función

#include <iostream>
using namespace std;

//普通函数与函数模板的调用规则
//1. 如果函数模板和普通函数都可以实现,优先调用普通函数
//2. 可以通过空模板参数列表来强制调用函数模板
//3. 函数模板也可以发生重载
//4. 如果函数模板可以产生更好的匹配, 优先调用函数模板


void myPrint(int a,int b)
{
	cout << "调用的是普通函数" << endl;
}

template <typename T>
void myPrint(T a, T b)
{
	cout << "调用的是函数模版" << endl;
}

//3. 函数模板也可以发生重载
template <typename T>
void myPrint(T a, T b,T c)
{
	cout << "调用的是重载函数模版" << endl;
}

void test05()
{
	int a = 10;
	int b = 20;
	myPrint(a, b);        //优先普通函数  【如果普通函数只有声明,会报错】
	

	//通过空模版参数列表,强制调用函数模版
	myPrint<>(a, b);     //函数模版

	myPrint(a, b, 100);

	//4. 如果函数模板可以产生更好的匹配, 优先调用函数模板
	char c1 = 'a';
	char c2 = 'b';
	myPrint(c1, c2);    //调用普通的需要转换,所以是调用模版
}

int main(void)
{
	test05();

	system("pause");
	return 0;
}

Resumen: dado que se proporcionan plantillas de funciones, es mejor no proporcionar funciones ordinarias, de lo contrario es probable que se produzca ambigüedad

5 Limitaciones de las plantillas

limitación:

  • La versatilidad de las plantillas no es una panacea

P.ej:

	template<class T>
	void f(T a, T b)
	{ 
    	a = b;
    }

La operación de asignación proporcionada en el código anterior, si las entradas ayb son una matriz, no se puede implementar

Otro ejemplo:

template<class T>
void f(T a, T b)
{ 
    if(a > b) { ... }
}

En el código anterior, si el tipo de datos de T se pasa en un tipo de datos personalizado como Persona, no funcionará correctamente.

 

Por lo tanto, para resolver este problema, C ++ proporciona una sobrecarga de plantillas, que puede proporcionar plantillas específicas para estos tipos específicos .

#include <iostream>
#include <string>
using namespace std;

//自定义数据类型
class Person
{
public:
	Person(string name,int age):m_Name(name),m_Age(age)
	{

	}
	string m_Name;
	int m_Age;
};


//对比两个数据是否相等
template <class T>
bool myCompare(T& a, T& b)
{
	if (a == b)
	{
		return true;
	}
	return false;
}

void test06()
{
	int a = 10;
	int b = 10;
	bool ret = myCompare(a, b);

	if (ret)
	{
		cout <<"a == b" << endl;
	}
	else
	{
		cout << "a != b" << endl;
	}
	
}


//利用具体化Person的版本实现代码,具体化优先调用
template<> bool myCompare(Person& p1, Person& p2)
{
	if (p1.m_Name == p2.m_Name && p1.m_Age == p2.m_Age)
	{
		return true;
	}
	return false;
}


//自定义数据类型的比较
void test006()
{
	Person p1("Tom", 10);
	Person p2("Tom", 10);
	bool ret = myCompare(p1, p2);

	if (ret)
	{
		cout << "p1 == p2" << endl;
	}
	else
	{
		cout << "p1 != p2" << endl;
	}
}

int main(void)
{
	test06();

	test006();

	system("pause");
	return 0;
}

para resumir:

  • El uso de plantillas específicas puede resolver la generalización de tipos personalizados

  • El aprendizaje de plantillas no es escribir plantillas, sino utilizar las plantillas proporcionadas por el sistema en STL.

Supongo que te gusta

Origin blog.csdn.net/Zhouzi_heng/article/details/114703371
Recomendado
Clasificación