[C ++ Mejorar la programación] 1. Plantilla

@ [TOC】

1 plantilla

1.1 El concepto de plantillas

La plantilla es para establecer un molde universal , lo que mejora enormemente la reutilización.

Por ejemplo, plantillas en la vida.

Plantilla de foto de una pulgada:

Plantilla PPT:

Características de la plantilla:

  • La plantilla no se puede usar directamente, es solo un marco
  • La plantilla universal no es una panacea

1.2 Plantilla de función

  • Otra idea de programación de C ++ se llama Programación genérica , La principal tecnología utilizada es la plantilla.

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

1.2.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

Ejemplo:


//交换整型函数
void swapInt(int& a, int& b) {
	int temp = a;
	a = b;
	b = temp;
}

//交换浮点型函数
void swapDouble(double& a, double& b) {
	double temp = a;
	a = b;
	b = temp;
}

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

void test01()
{
	int a = 10;
	int b = 20;
	
	//swapInt(a, b);

	//利用模板实现交换
	//1、自动类型推导
	mySwap(a, b);

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

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

}

int main() {

	test01();

	system("pause");

	return 0;
}

para resumir:

  • La plantilla de función utiliza una plantilla de palabras clave
  • Hay dos formas de utilizar las plantillas de funciones: inferencia automática de tipos, mostrar tipos especificados
  • El propósito de la plantilla es mejorar la reutilización y parametrizar el tipo

1.2.2 Precauciones para las plantillas de funciones

Precauciones:

  • Derivación automática de tipo, debe derivar un tipo de datos consistente T antes de que pueda usarse

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

Ejemplo:

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


// 1、自动类型推导,必须推导出一致的数据类型T,才可以使用
void test01()
{
	int a = 10;
	int b = 20;
	char c = 'c';

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


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

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

int main() {

	test01();
	test02();

	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

1.2.3 Ejemplo de plantilla de función

Descripción del caso:

  • Use una plantilla de función para encapsular una función de clasificación, que puede clasificar matrices de diferentes tipos de datos
  • Las reglas de clasificación son de grandes a pequeñas, el algoritmo de clasificación es la clasificación por selección
  • Prueba usando la matriz char y la matriz int respectivamente

Ejemplo:

//交换的函数模板
template<typename T>
void mySwap(T &a, T&b)
{
	T temp = a;
	a = b;
	b = temp;
}


template<class T> // 也可以替换成typename
//利用选择排序,进行对数组从大到小的排序
void mySort(T arr[], int len)
{
	for (int i = 0; i < len; i++)
	{
		int max = i; //最大数的下标
		for (int j = i + 1; j < len; j++)
		{
			if (arr[max] < arr[j])
			{
				max = j;
			}
		}
		if (max != i) //如果最大数的下标不是i,交换两者
		{
			mySwap(arr[max], arr[i]);
		}
	}
}
template<typename T>
void printArray(T arr[], int len) {

	for (int i = 0; i < len; i++) {
		cout << arr[i] << " ";
	}
	cout << endl;
}
void test01()
{
	//测试char数组
	char charArr[] = "bdcfeagh";
	int num = sizeof(charArr) / sizeof(char);
	mySort(charArr, num);
	printArray(charArr, num);
}

void test02()
{
	//测试int数组
	int intArr[] = { 7, 5, 8, 1, 3, 9, 2, 4, 6 };
	int num = sizeof(intArr) / sizeof(int);
	mySort(intArr, num);
	printArray(intArr, num);
}

int main() {

	test01();
	test02();

	system("pause");

	return 0;
}

Resumen: las plantillas pueden mejorar la reutilización del código y requieren competencia

1.2.4 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 usa la visualización del tipo especificado, puede ocurrir una conversión de tipo implícita

Ejemplo:

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

//函数模板
template<class T>
T myAdd02(T a, T b)  
{
	return a + b;
}

//使用函数模板时,如果用自动类型推导,不会发生自动类型转换,即隐式类型转换
void test01()
{
	int a = 10;
	int b = 20;
	char c = 'c';
	
	cout << myAdd01(a, c) << endl; //正确,将char类型的'c'隐式转换为int类型  'c' 对应 ASCII码 99

	//myAdd02(a, c); // 报错,使用自动类型推导时,不会发生隐式类型转换

	myAdd02<int>(a, c); //正确,如果用显示指定类型,可以发生隐式类型转换
}

int main() {

	test01();

	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

1.2.5 Llamar a reglas de funciones ordinarias y plantillas de funciones

Las reglas de llamada son las siguientes:

  1. Si tanto la plantilla de función como la función ordinaria se pueden realizar, la función ordinaria se llama primero
  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

Ejemplo:

//普通函数与函数模板调用规则
void myPrint(int a, int b)
{
	cout << "调用的普通函数" << endl;
}

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

template<typename T>
void myPrint(T a, T b, T c) 
{ 
	cout << "调用重载的模板" << endl; 
}

void test01()
{
	//1、如果函数模板和普通函数都可以实现,优先调用普通函数
	// 注意 如果告诉编译器  普通函数是有的,但只是声明没有实现,或者不在当前文件内实现,就会报错找不到
	int a = 10;
	int b = 20;
	myPrint(a, b); //调用普通函数

	//2、可以通过空模板参数列表来强制调用函数模板
	myPrint<>(a, b); //调用函数模板

	//3、函数模板也可以发生重载
	int c = 30;
	myPrint(a, b, c); //调用重载的函数模板

	//4、 如果函数模板可以产生更好的匹配,优先调用函数模板
	char c1 = 'a';
	char c2 = 'b';
	myPrint(c1, c2); //调用函数模板
}

int main() {

	test01();

	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

1.2.6 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 .

Ejemplo:

#include<iostream>
using namespace std;

#include <string>

class Person
{
public:
	Person(string name, int age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}
	string m_Name;
	int m_Age;
};

//普通函数模板
template<class T>
bool myCompare(T& a, T& b)
{
	if (a == b)
	{
		return true;
	}
	else
	{
		return false;
	}
}


//具体化,显示具体化的原型和定意思以template<>开头,并通过名称来指出类型
//具体化优先于常规模板
template<> bool myCompare(Person &p1, Person &p2)
{
	if ( p1.m_Name  == p2.m_Name && p1.m_Age == p2.m_Age)
	{
		return true;
	}
	else
	{
		return false;
	}
}

void test01()
{
	int a = 10;
	int b = 20;
	//内置数据类型可以直接使用通用的函数模板
	bool ret = myCompare(a, b);
	if (ret)
	{
		cout << "a == b " << endl;
	}
	else
	{
		cout << "a != b " << endl;
	}
}

void test02()
{
	Person p1("Tom", 10);
	Person p2("Tom", 10);
	//自定义数据类型,不会调用普通的函数模板
	//可以创建具体化的Person数据类型的模板,用于特殊处理这个类型
	bool ret = myCompare(p1, p2);
	if (ret)
	{
		cout << "p1 == p2 " << endl;
	}
	else
	{
		cout << "p1 != p2 " << endl;
	}
}

int main() {

	test01();

	test02();

	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.

1.3 Plantilla de clase

1.3.1 Sintaxis de la plantilla de clase

Función de plantilla de clase:

  • Establezca una clase general, el tipo de datos del miembro en la clase no se puede especificar específicamente, representado 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

Ejemplo:

#include <string>
//类模板
template<class NameType, class AgeType> 
class Person
{
public:
	Person(NameType name, AgeType age)
	{
		this->mName = name;
		this->mAge = age;
	}
	void showPerson()
	{
		cout << "name: " << this->mName << " age: " << this->mAge << endl;
	}
public:
	NameType mName;
	AgeType mAge;
};

void test01()
{
	// 指定NameType 为string类型,AgeType 为 int类型
	Person<string, int>P1("孙悟空", 999);
	P1.showPerson();
}

int main() {

	test01();

	system("pause");

	return 0;
}

Resumen: La sintaxis de una plantilla de clase y una plantilla de función es similar. Agregue una clase después de la plantilla de plantilla de declaración. Esta clase se llama plantilla de clase

1.3.2 La diferencia entre plantilla de clase y plantilla de función

Hay dos diferencias principales entre una plantilla de clase y una plantilla de función:

  1. No hay forma de utilizar la inferencia de tipo automática para las plantillas de clases.
  2. Las plantillas de clase pueden tener parámetros predeterminados en la lista de parámetros de la plantilla

Ejemplo:

#include <string>
//类模板
template<class NameType, class AgeType = int> 
class Person
{
public:
	Person(NameType name, AgeType age)
	{
		this->mName = name;
		this->mAge = age;
	}
	void showPerson()
	{
		cout << "name: " << this->mName << " age: " << this->mAge << endl;
	}
public:
	NameType mName;
	AgeType mAge;
};

//1、类模板没有自动类型推导的使用方式
void test01()
{
	// Person p("孙悟空", 1000); // 错误 类模板使用时候,不可以用自动类型推导
	Person <string ,int>p("孙悟空", 1000); //必须使用显示指定类型的方式,使用类模板
	p.showPerson();
}

//2、类模板在模板参数列表中可以有默认参数
void test02()
{
	Person <string> p("猪八戒", 999); //类模板中的模板参数列表 可以指定默认参数
	p.showPerson();
}

int main() {

	test01();

	test02();

	system("pause");

	return 0;
}

para resumir:

  • Las plantillas de clase solo se pueden usar para mostrar el tipo especificado
  • La lista de parámetros de la plantilla en la plantilla de clase puede tener parámetros predeterminados

1.3.3 Cuándo crear una función miembro en una plantilla de clase

Hay una diferencia en el tiempo de creación de las funciones miembro en la plantilla de clase y las funciones miembro en la clase ordinaria:

  • Las funciones miembro en clases ordinarias se pueden crear desde el principio
  • Las funciones miembro en la plantilla de clase se crean cuando se llaman

Ejemplo:

class Person1
{
public:
	void showPerson1()
	{
		cout << "Person1 show" << endl;
	}
};

class Person2
{
public:
	void showPerson2()
	{
		cout << "Person2 show" << endl;
	}
};

template<class T>
class MyClass
{
public:
	T obj;

	//类模板中的成员函数,并不是一开始就创建的,而是在模板调用时再生成

	void fun1() { obj.showPerson1(); }
	void fun2() { obj.showPerson2(); }

};

void test01()
{
	MyClass<Person1> m;
	
	m.fun1();

	//m.fun2();//编译会出错,说明函数调用才会去创建成员函数
}

int main() {

	test01();

	system("pause");

	return 0;
}

Resumen: Las funciones miembro en la plantilla de clase no se crean al principio, se crean cuando se llaman

1.3.4 Objeto de plantilla de clase como parámetro de función

objetivo de aprendizaje:

  • El objeto instanciado por la plantilla de clase, la forma de pasar parámetros a la función

Hay tres métodos de entrada:

  1. Especifique el tipo de entrada: muestre directamente el tipo de datos del objeto
  2. Plantillas de parámetros: los parámetros del objeto se transforman en plantillas para su transmisión
  3. Plantilla de clase completa: plantilla de este tipo de objeto para la entrega

Ejemplo:

#include <string>
//类模板
template<class NameType, class AgeType = int> 
class Person
{
public:
	Person(NameType name, AgeType age)
	{
		this->mName = name;
		this->mAge = age;
	}
	void showPerson()
	{
		cout << "name: " << this->mName << " age: " << this->mAge << endl;
	}
public:
	NameType mName;
	AgeType mAge;
};

//1、指定传入的类型
void printPerson1(Person<string, int> &p) 
{
	p.showPerson();
}
void test01()
{
	Person <string, int >p("孙悟空", 100);
	printPerson1(p);
}

//2、参数模板化
template <class T1, class T2>
void printPerson2(Person<T1, T2>&p)
{
	p.showPerson();
	cout << "T1的类型为: " << typeid(T1).name() << endl;
	cout << "T2的类型为: " << typeid(T2).name() << endl;
}
void test02()
{
	Person <string, int >p("猪八戒", 90);
	printPerson2(p);
}

//3、整个类模板化
template<class T>
void printPerson3(T & p)
{
	cout << "T的类型为: " << typeid(T).name() << endl;
	p.showPerson();

}
void test03()
{
	Person <string, int >p("唐僧", 30);
	printPerson3(p);
}

int main() {

	test01();
	test02();
	test03();

	system("pause");

	return 0;
}

para resumir:

  • Hay tres formas de pasar parámetros a la función del objeto creado por la plantilla de clase
  • El más utilizado es el primero: especificar el tipo de entrada

1.3.5 Plantillas de clase y herencia

Cuando la plantilla de clase encuentra herencia, debe prestar atención a los siguientes puntos:

  • Cuando la clase principal heredada por la subclase es una plantilla de clase, cuando se declara la subclase, se debe especificar el tipo de T en la clase principal
  • Si no se especifica, el compilador no puede asignar memoria a la subclase
  • Si desea especificar de manera flexible el tipo de T en la clase principal, la subclase también debe convertirse en una plantilla de clase

Ejemplo:

template<class T>
class Base
{
	T m;
};

//class Son:public Base  //错误,c++编译需要给子类分配内存,必须知道父类中T的类型才可以向下继承
class Son :public Base<int> //必须指定一个类型
{
};
void test01()
{
	Son c;
}

//类模板继承类模板 ,可以用T2指定父类中的T类型
template<class T1, class T2>
class Son2 :public Base<T2>
{
public:
	Son2()
	{
		cout << typeid(T1).name() << endl;
		cout << typeid(T2).name() << endl;
	}
};

void test02()
{
	Son2<int, char> child1;
}


int main() {

	test01();

	test02();

	system("pause");

	return 0;
}

Resumen: si la clase principal es una plantilla de clase, la subclase debe especificar el tipo de datos de T en la clase principal

1.3.6 Implementación de función de miembro de plantilla de clase fuera de la clase

Objetivo de aprendizaje: ser capaz de dominar la implementación de funciones miembro en la plantilla de la clase fuera de la clase.

Ejemplo:

#include <string>

//类模板中成员函数类外实现
template<class T1, class T2>
class Person {
public:
	//成员函数类内声明
	Person(T1 name, T2 age);
	void showPerson();

public:
	T1 m_Name;
	T2 m_Age;
};

//构造函数 类外实现
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age) {
	this->m_Name = name;
	this->m_Age = age;
}

//成员函数 类外实现
template<class T1, class T2>
void Person<T1, T2>::showPerson() {
	cout << "姓名: " << this->m_Name << " 年龄:" << this->m_Age << endl;
}

void test01()
{
	Person<string, int> p("Tom", 20);
	p.showPerson();
}

int main() {

	test01();

	system("pause");

	return 0;
}

Resumen: cuando la función miembro en la plantilla de la clase se implementa fuera de la clase, es necesario agregar la lista de parámetros de la plantilla

1.3.7 Compilación de archivos de plantilla de clase

objetivo de aprendizaje:

  • Comprender los problemas y las soluciones que surgen de la compilación de funciones de miembros de la plantilla de clase en archivos separados

problema:

  • El momento de creación de la función miembro en la plantilla de clase es en la fase de llamada, lo que conduce a la falla de vincular al escribir subarchivos.

resolver:

  • Solución 1: incluya directamente el archivo fuente .cpp
  • Solución 2: escriba la declaración y la implementación en el mismo archivo y cambie el sufijo a .hpp, hpp es el nombre acordado, no obligatorio

Ejemplo:

El código en person.hpp:

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

template<class T1, class T2>
class Person {
public:
	Person(T1 name, T2 age);
	void showPerson();
public:
	T1 m_Name;
	T2 m_Age;
};

//构造函数 类外实现
template<class T1, class T2>
Person<T1, T2>::Person(T1 name, T2 age) {
	this->m_Name = name;
	this->m_Age = age;
}

//成员函数 类外实现
template<class T1, class T2>
void Person<T1, T2>::showPerson() {
	cout << "姓名: " << this->m_Name << " 年龄:" << this->m_Age << endl;
}

La plantilla de la clase se divide en archivos para escribir el código en .cpp

#include<iostream>
using namespace std;

//#include "person.h"
#include "person.cpp" //解决方式1,包含cpp源文件

//解决方式2,将声明和实现写到一起,文件后缀名改为.hpp
#include "person.hpp"
void test01()
{
	Person<string, int> p("Tom", 10);
	p.showPerson();
}

int main() {

	test01();

	system("pause");

	return 0;
}

Resumen: La solución principal es la segunda, escriba las funciones de los miembros de la plantilla de clase juntas y cambie el nombre del sufijo a .hpp

1.3.8 Plantillas de clase y amigos

objetivo de aprendizaje:

  • Domine la implementación en clase y fuera de clase de plantillas de clase y funciones de amigos

Realización de funciones globales en una clase: puede declarar amigos directamente en la clase

Implementación de funciones globales fuera de la clase: debe informar al compilador de antemano la existencia de funciones globales

Ejemplo:

#include <string>

//2、全局函数配合友元  类外实现 - 先做函数模板声明,下方在做函数模板定义,在做友元
template<class T1, class T2> class Person;

//如果声明了函数模板,可以将实现写到后面,否则需要将实现体写到类的前面让编译器提前看到
//template<class T1, class T2> void printPerson2(Person<T1, T2> & p); 

template<class T1, class T2>
void printPerson2(Person<T1, T2> & p)
{
	cout << "类外实现 ---- 姓名: " << p.m_Name << " 年龄:" << p.m_Age << endl;
}

template<class T1, class T2>
class Person
{
	//1、全局函数配合友元   类内实现
	friend void printPerson(Person<T1, T2> & p)
	{
		cout << "姓名: " << p.m_Name << " 年龄:" << p.m_Age << endl;
	}


	//全局函数配合友元  类外实现
	friend void printPerson2<>(Person<T1, T2> & p);

public:

	Person(T1 name, T2 age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}


private:
	T1 m_Name;
	T2 m_Age;

};

//1、全局函数在类内实现
void test01()
{
	Person <string, int >p("Tom", 20);
	printPerson(p);
}


//2、全局函数在类外实现
void test02()
{
	Person <string, int >p("Jerry", 30);
	printPerson2(p);
}

int main() {

	//test01();

	test02();

	system("pause");

	return 0;
}

Resumen: se recomienda que la función global se implemente en la clase, el uso es simple y el compilador puede reconocerlo directamente

1.3.9 Caso de plantilla de clase

Descripción del caso: para implementar una clase de matriz general, los requisitos son los siguientes:

  • Puede almacenar datos de tipos de datos integrados y tipos de datos personalizados
  • Almacene los datos en la matriz en el área del montón
  • La capacidad de la matriz se puede pasar al constructor.
  • Proporcione el constructor de copia y el operador correspondientes = para evitar problemas de copia superficial
  • Proporcione métodos de interpolación de cola y eliminación de cola para agregar y eliminar datos en la matriz
  • Puede acceder a los elementos de la matriz subindicando
  • Puede obtener el número actual de elementos en la matriz y la capacidad de la matriz

Ejemplo:

Código en myArray.hpp

#pragma once
#include <iostream>
using namespace std;

template<class T>
class MyArray
{
public:
    
	//构造函数
	MyArray(int capacity)
	{
		this->m_Capacity = capacity;
		this->m_Size = 0;
		pAddress = new T[this->m_Capacity];
	}

	//拷贝构造
	MyArray(const MyArray & arr)
	{
		this->m_Capacity = arr.m_Capacity;
		this->m_Size = arr.m_Size;
		this->pAddress = new T[this->m_Capacity];
		for (int i = 0; i < this->m_Size; i++)
		{
			//如果T为对象,而且还包含指针,必须需要重载 = 操作符,因为这个等号不是 构造 而是赋值,
			// 普通类型可以直接= 但是指针类型需要深拷贝
			this->pAddress[i] = arr.pAddress[i];
		}
	}

	//重载= 操作符  防止浅拷贝问题
	MyArray& operator=(const MyArray& myarray) {

		if (this->pAddress != NULL) {
			delete[] this->pAddress;
			this->m_Capacity = 0;
			this->m_Size = 0;
		}

		this->m_Capacity = myarray.m_Capacity;
		this->m_Size = myarray.m_Size;
		this->pAddress = new T[this->m_Capacity];
		for (int i = 0; i < this->m_Size; i++) {
			this->pAddress[i] = myarray[i];
		}
		return *this;
	}

	//重载[] 操作符  arr[0]
	T& operator [](int index)
	{
		return this->pAddress[index]; //不考虑越界,用户自己去处理
	}

	//尾插法
	void Push_back(const T & val)
	{
		if (this->m_Capacity == this->m_Size)
		{
			return;
		}
		this->pAddress[this->m_Size] = val;
		this->m_Size++;
	}

	//尾删法
	void Pop_back()
	{
		if (this->m_Size == 0)
		{
			return;
		}
		this->m_Size--;
	}

	//获取数组容量
	int getCapacity()
	{
		return this->m_Capacity;
	}

	//获取数组大小
	int	getSize()
	{
		return this->m_Size;
	}


	//析构
	~MyArray()
	{
		if (this->pAddress != NULL)
		{
			delete[] this->pAddress;
			this->pAddress = NULL;
			this->m_Capacity = 0;
			this->m_Size = 0;
		}
	}

private:
	T * pAddress;  //指向一个堆空间,这个空间存储真正的数据
	int m_Capacity; //容量
	int m_Size;   // 大小
};

Plantilla de clase case-Array class encapsulation.cpp

#include "myArray.hpp"
#include <string>

void printIntArray(MyArray<int>& arr) {
	for (int i = 0; i < arr.getSize(); i++) {
		cout << arr[i] << " ";
	}
	cout << endl;
}

//测试内置数据类型
void test01()
{
	MyArray<int> array1(10);
	for (int i = 0; i < 10; i++)
	{
		array1.Push_back(i);
	}
	cout << "array1打印输出:" << endl;
	printIntArray(array1);
	cout << "array1的大小:" << array1.getSize() << endl;
	cout << "array1的容量:" << array1.getCapacity() << endl;

	cout << "--------------------------" << endl;

	MyArray<int> array2(array1);
	array2.Pop_back();
	cout << "array2打印输出:" << endl;
	printIntArray(array2);
	cout << "array2的大小:" << array2.getSize() << endl;
	cout << "array2的容量:" << array2.getCapacity() << endl;
}

//测试自定义数据类型
class Person {
public:
	Person() {} 
		Person(string name, int age) {
		this->m_Name = name;
		this->m_Age = age;
	}
public:
	string m_Name;
	int m_Age;
};

void printPersonArray(MyArray<Person>& personArr)
{
	for (int i = 0; i < personArr.getSize(); i++) {
		cout << "姓名:" << personArr[i].m_Name << " 年龄: " << personArr[i].m_Age << endl;
	}

}

void test02()
{
	//创建数组
	MyArray<Person> pArray(10);
	Person p1("孙悟空", 30);
	Person p2("韩信", 20);
	Person p3("妲己", 18);
	Person p4("王昭君", 15);
	Person p5("赵云", 24);

	//插入数据
	pArray.Push_back(p1);
	pArray.Push_back(p2);
	pArray.Push_back(p3);
	pArray.Push_back(p4);
	pArray.Push_back(p5);

	printPersonArray(pArray);

	cout << "pArray的大小:" << pArray.getSize() << endl;
	cout << "pArray的容量:" << pArray.getCapacity() << endl;

}

int main() {

	//test01();

	test02();

	system("pause");

	return 0;
}

para resumir:

Capaz de utilizar los puntos de conocimiento aprendidos para realizar una matriz universal

Para obtener más información, siga la cuenta oficial:
img

Supongo que te gusta

Origin blog.csdn.net/yegeli/article/details/114441825
Recomendado
Clasificación