C++经典问题_16 模板

一. 模板的概念

  1. 模板就是建立通用的工具,提高代码的复用性.
  2. 模板不能直接使用,大部分的时候只是一个框架
  3. 模板的通用并不是万能的

二. 函数模板

① 函数模板介绍
  1. C++有一种编程思想称为泛型编程,主要利用的技术就是模板
  2. 函数模板的作用: 建立一个通用的函数,其函数返回值类型和形参类型可以不具体制定,用一个虚拟的类型来代表.
② 函数模板语法
template <typename T>
函数声明或者定义
  1. template – 声明创建模模板
  2. typename – 表明后面的符号是一种数据类型,其中typename可以用class来代替
  3. T – 声明的通用的数据类型,名称可以替换,一般为大写字母.
/*----------------------------------------------------------------
* 项目: Classical Question
* 作者: Fioman
* 邮箱: geym@hengdingzhineng.com
* 时间: 2022/3/22
* 格言: Talk is cheap,show me the code ^_^
//----------------------------------------------------------------*/

#include <iostream>
using namespace std;
// 函数模板

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

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

// 如果还有其他的类型,就必须要继续的添加函数.
template <typename T> // 函数模板
void swap_two_number(T &t1, T &t2)
{
	T temp;
	temp = t1;
	t1 = t2;
	t2 = temp;
}


int main()
{
	int a = 10;
	int b = 20;

	// 函数模板的使用方式
	// 1. 自动类型推导
	swap_two_number(a, b);

	// 2. 显示指定类型
	double c = 3.2;
	double d = 3.4;
	swap_two_number<double>(c, d);
	system("pause");
	return 0;
}

模板函数使用方式:

  1. 自动类型推导
  2. 指定参数模板类型
③ 函数模板的注意事项
  1. 自动类型推导,必须推导出一致的数据类型T,才可以使用
  2. 模板必须要确定出T的数据类型,才可以使用.
/*----------------------------------------------------------------
* 项目: Classical Question
* 作者: Fioman
* 邮箱: geym@hengdingzhineng.com
* 时间: 2022/3/22
* 格言: Talk is cheap,show me the code ^_^
//----------------------------------------------------------------*/

#include <iostream>
using namespace std;
// 1. 自动类型推导,必须推导出一致的数据类型T才可以使用
template <typename T>
void swap_number(T &t1, T &t2)
{
	T temp = t1;
	t1 = t2;
	t2 = temp;
}


void test_01(void)
{
	int a = 10;
	int b = 20;
	// 自动类型推导,两个类型一致,可以推测出一致的类型
 	swap_number(a, b); 
	cout << "a = " << a << " b = " << b << endl;
}

void test_02(void)
{
	int a = 10;
	double b = 10.5;
	// 自动类型推导,两个类型不一致,不可以推测出一致的类型
	//swap_number(a, b);  这里会报错,参数类型不匹配.推导不出来一致的类型
}

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


void test_03(void)
{
	// func(); // 模板函数必须确定T的类型,才能使用,即使函数中没有这个类型参数
	func<int>();// 正确
}
int main()
{
	test_01();

	system("pause");
	return 0;
}

④ 函数模板的例子
  1. 利用模板函数封装一个排序的函数,可以对不同的数据类型数组进行排序
  2. 排序规则从大到小,排序算法为选择排序
  3. 分别利用char数组和int数组以及double数组进行测试
/*----------------------------------------------------------------
* 项目: Classical Question
* 作者: Fioman
* 邮箱: geym@hengdingzhineng.com
* 时间: 2022/3/22
* 格言: Talk is cheap,show me the code ^_^
//----------------------------------------------------------------*/

#include <iostream>
using namespace std;
// 对数组进行排序的函数

template <typename T>
void my_swap_template(T &a, T &b)
{
	T temp = a;
	a = b;
	b = temp;
}

// 打印模板
template <typename T>
void print_arr_template(T arr[], int len)
{
	for (int i = 0; i < len; i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
}


// 排序算法
template <typename T>
void sort_template(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)
		{
			// 交换 max 和 i的元素
			my_swap_template(arr[max], arr[i]); // 交换两个数
		}
	}
}



void test_01()
{
	// 测试char数组
	char charArr[] = "badcfe";
	int arrLen = sizeof(charArr) / sizeof(charArr[0]);
	sort_template(charArr, arrLen);
	print_arr_template(charArr, arrLen);

	int intArr[] = { 2,3,4,1,5,6,8,7 };
	arrLen = sizeof(intArr) / sizeof(intArr[0]);
	sort_template(intArr, arrLen);
	print_arr_template(intArr, arrLen);

	double doubleArr[] = { 1.2,3.4,5.6,0.8,9.1,3.2 };
	arrLen = sizeof(doubleArr) / sizeof(doubleArr[0]);
	sort_template(doubleArr, arrLen);
	print_arr_template(doubleArr, arrLen);

}
int main()
{

	test_01();
	system("pause");
	return 0;
}

三. 函数模板和普通函数的区别

  1. 普通函数调用可以发生隐式类型转换
  2. 函数模板,使用自动类型推导,不可以发生隐式类型转换.
  3. 函数模板 用显示指定类型,可以发生隐式类型转换.
/*----------------------------------------------------------------
* 项目: Classical Question
* 作者: Fioman
* 邮箱: geym@hengdingzhineng.com
* 时间: 2022/3/22
* 格言: Talk is cheap,show me the code ^_^
//----------------------------------------------------------------*/

#include <iostream>
using namespace std;
// 1.普通函数调用可以发生隐式类型转换

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

// 函数模板,不能发生隐式类型转换
template <typename T>
int my_add_template(T a, T b)
{
	return a + b;
}

void test_01(void)
{
	int a = 10;
	int b = 10;
	cout << my_add(a, b) << endl;

	char c = 'c';
	// 普通函数的隐式类型转换 c会通过ascii码获取整数,然后和a相加
	cout << my_add(a, c) << endl;

	//cout << my_add_template(a, c) << endl; 报错,参数类型匹配错误

	// 显示指定类型,可以发生隐式类型转换
	cout << my_add_template<int>(a, c) << endl;

}
int main()
{

	test_01();
	system("pause");
	return 0;
}

四. 普通函数和函数模板的调用规则

  1. 如果函数模板和普通函数都满足调用条件,优先使用普通函数.
  2. 可以通过空模板参数列表来强制调用函数模板
  3. 函数模板也可以发生重载
  4. 如果函数模板可以产生更好的匹配,优先调用函数模板.也就是说模板调用优先于普通的隐式类型转换的调用.
/*----------------------------------------------------------------
* 项目: Classical Question
* 作者: Fioman
* 邮箱: geym@hengdingzhineng.com
* 时间: 2022/3/22
* 格言: Talk is cheap,show me the code ^_^
//----------------------------------------------------------------*/

#include <iostream>
using namespace std;
// 1. 如果函数模板和普通函数都可以调用,优先调用普通函数
// 2. 如果通过空模板参数列表,强制调用函数模板
// 3. 函数模板可以发生重载
// 4. 如果函数模板可以产生更好的匹配,优先调用函数模板

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

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

template <typename T>
void my_print(T a, T b, T c)
{
	cout << "调动三个参数的模板函数" << endl;
}

void test_01(void)
{
	int a = 10;
	int b = 20;
	my_print(a, b); // 调用普通的函数,如果普通的函数,只有定义没有实现,会报错.

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

	// 函数模板的重载
	my_print(a, b, 30);// 调用的是三个参数的模板函数

	// 如果函数模板产生更好的匹配,优先调用函数模板
	char c1 = 'a';
	char c2 = 'b';

	// 这里如果没有模板函数,会通过隐式类型转换调用普通的函数.
	// 如果模板函数存在,并且符合调用,会调用函数模板
	my_print(c1, c2); // 这里调用的是函数模板
}

int main()
{
	test_01();
	system("pause");
	return 0;
}

结果:

五. 模板的局限性

  1. 模板的通用性不是万能的
  2. 有些特定的数据类型,需要具体化方式做特殊实现
  3. 利用具体化的模板,可以解决自定义类型的通用性
  4. 学习模板并不是为了写模板,而是在STL能够运行系统提供的模板
/*----------------------------------------------------------------
* 项目: Classical Question
* 作者: Fioman
* 邮箱: geym@hengdingzhineng.com
* 时间: 2022/3/22
* 格言: Talk is cheap,show me the code ^_^
//----------------------------------------------------------------*/

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

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


template <typename T>
bool my_compare(T &a, T &b)
{
	return a == b;
}

// Person类型的具体化实现,告诉编译器这是一个具体化的模板,如果是Person类型,优先调用这个重载的函数模板
template<> bool my_compare(Person &p1, Person &p2)
{
	return p1.mName == p2.mName && p2.mAge == p2.mAge;
}


void test_01(void)
{
	int a = 10;
	int b = 20;
	bool ret;
	ret = my_compare(a, b);
	if (ret)
	{
		cout << "a 和 b相等!" << endl;
	}
	else
	{
		cout << "a 和 b不相等!" << endl;
	}

	// 如果是自定义类型
	Person p1("Tom", 10);
	Person p2("Tom", 10);

	ret = my_compare(p1, p2);
	if (ret)
	{
		cout << "p1 和 p2 相等!" << endl;
	}
	else
	{
		cout << "p1 和 p2 不相等!" << endl;
	}

}

int main()
{
	test_01();
	system("pause");
	return 0;
}

六 类模板

① 类模板的作用

建立一个通用的类,类中的成员 数据类型可以不具体制定,用一个虚拟的类型来代表.

② 语法
template <typename T>
类定义
③ 例子
/*----------------------------------------------------------------
* 项目: Classical Question
* 作者: Fioman
* 邮箱: geym@hengdingzhineng.com
* 时间: 2022/3/22
* 格言: Talk is cheap,show me the code ^_^
//----------------------------------------------------------------*/

#include <iostream>
#include <string>
using namespace std;
// 类模板
template <class NameType ,class AgeType>
class Person
{
public:
	Person(NameType name, AgeType age)
	{
		this->mName = name;
		this->mAge = age;
	}

	void show_person()
	{
		cout << "姓名: " << this->mName << " 年龄: " << this->mAge << endl;
	}
public:
	NameType mName;
	AgeType mAge;
};

void test_01(void)
{
	// 显示的指定类型
	Person<string, int> p1("孙悟空", 1111);
	p1.show_person();

	// 自动类型判定,如果是类模板,必须指定参数列表
	// Person p2("猪八戒",20);
	Person<int, int > p2(1, 2);
	p2.show_person();
}

int main()
{
	test_01();

	system("pause");
	return 0;
}

④ 类模板和函数模板的区别
  1. 类模板没有自动类型推导的使用方式,也就是说,类模板必须要显示的指定模板的形参类型
  2. 类模板在模板参数列表中可以有默认参数
/*----------------------------------------------------------------
* 项目: Classical Question
* 作者: Fioman
* 邮箱: geym@hengdingzhineng.com
* 时间: 2022/3/22
* 格言: Talk is cheap,show me the code ^_^
//----------------------------------------------------------------*/
#include <iostream>
using namespace std;
template <class NameType,class AgeType=int>
class Person
{
public:
	Person(NameType name, AgeType age)
	{
		this->mName = name;
		this->mAge = age;
	}

	void show_person()
	{
		cout << "姓名: " << this->mName << " 年龄: " << this->mAge << endl;
	}
public:
	NameType mName;
	AgeType mAge;
};

// 1. 类模板没有自动类型推导使用方式
void test_01(void)
{
	//Person p1("孙悟空", 1000); // 错误,无法使用自动类型推导
	Person<string, int> p2("孙悟空", 1000); // 正确,只能显示指定类型
	p2.show_person();
}

// 2. 类模板再模板参数列表中可以有默认的参数
void test_02(void)
{
	Person<string> p3("猪八戒", 10000); // 模板可以使用默然的类型int
	Person<string> p4("孙悟空", 1.2); // 这里相当于是 Person<string,int> p4("孙悟空",1.2);
	p3.show_person();
	p4.show_person();
}


int main()
{
	test_01();
	test_02();
	system("pause");
	return 0;
}

⑤ 类模板中成员函数的创建时机

类模板中成员函数和普通类中成员函数创建时机是有区别的:

  1. 普通类中的成员函数一开始就可以创建
  2. 类模板中的成员函数在调用的时候才创建
/*----------------------------------------------------------------
* 项目: Classical Question
* 作者: Fioman
* 邮箱: geym@hengdingzhineng.com
* 时间: 2022/3/22
* 格言: Talk is cheap,show me the code ^_^
//----------------------------------------------------------------*/

#include <iostream>
using namespace std;
class Person1
{
public:
	void show_person1(void)
	{
		cout << "Person1::show_person1()调用!" << endl;
	}
};

class Person2
{
public:
	void show_person2(void)
	{
		cout << "Person2::show_person2()调用!" << endl;
	}
};

template <class T>
class MyClass
{
public:
	T obj;
	void func1()
	{
		obj.show_person1();
	}

	void func2()
	{
		obj.show_person2();
	}
};

void test_01(void)
{
	MyClass<Person1> m;
	m.func1();
	//m.func2(); 编译运行的时候会报错,说明func2中的obj.show_person2()是在编译运行时才创建
	// 如果这里不调用,就不会报错,也证明了编译的时候,如果没有调用obj.show_person2()是没有创建的
	// 这个也很好理解,因为是模板类的成员函数,所以要在具体调用的时候才能确定是什么类型
	// 确定了是什么类型,才能进行创建
	// 如何调用func2呢,再声明一个模板
	MyClass<Person2> m2;
	m2.func2();

}

int main()
{

	test_01();
	system("pause");
	return 0;
}

七 类模板对象做函数参数

① 介绍
  1. 类模板也是可以实例化对象的
  2. 而这个实例化的对象是可以作为函数的参数的
② 参数传入的方式
  1. 指定传入的类型: 直接在参数列表中显示的指定模板参数的类型
  2. 参数模板化: 将对象中的参数变为模板进行传递,也就是在参数列表中使用模板,将函数定义为函数模板的方式
  3. 整个类模板化: 将这个对象类型 模板化进行传递.也就是整个类对象,当成一个模板来进行传参.
/*----------------------------------------------------------------
* 项目: Classical Question
* 作者: Fioman
* 邮箱: geym@hengdingzhineng.com
* 时间: 2022/3/22
* 格言: Talk is cheap,show me the code ^_^
//----------------------------------------------------------------*/
#include <iostream>
using namespace std;
// 类模板对象做函数参数
template <class T1,class T2>
class Person
{
public:
	Person(T1 name, T2 age)
	{
		this->mName = name;
		this->mAge = age;
	}
	void show_person()
	{
		cout << "姓名: " << this->mName << " 年龄: " << this->mAge << endl;
	}
public:
	T1 mName;
	T2 mAge;
};

// 1. 指定传入的类型,普通函数传参的方式
void print_info_01(Person<string, int> &p)
{
	p.show_person();
}

// 2. 使用函数模板,参数定义为模板的形式
template <typename T1,typename T2>
void print_info_02(Person<T1,T2> & p)
{
	p.show_person();
	cout << "T1的类型: " << typeid(T1).name() << endl;
	cout << "T2的类型: " << typeid(T2).name() << endl;
}

// 3.直接将整个类当成一个模板作为参数
template <typename T>
void print_info_03(T&p)
{
	p.show_person();
	cout << "T的类型: " << typeid(T).name() << endl;
}

void test_01(void)
{
	Person<string,int> p1("猪八戒", 100);
	print_info_01(p1);

	Person<string, int> p2("孙悟空", 1000);
	print_info_02(p2);

	Person<string, int> p3("唐僧", 20);
	print_info_03(p3);
}

int main()
{
	test_01();
	system("pause");
	return 0;
}

结果:

总结:

  1. 通过类模板创建的对象,可以有三种方式向函数中进行传参
  2. 使用比较广泛的是第一种: 指定传入的类型

八 类模板和继承

① 类模板碰到继承的时候,需要注意一下几点:
  1. 当子类继承的父类是一个类模板的时候,子类在声明的时候,要指定出父类中的T类型
  2. 如果不指定,编译器无法给予子类分配内存
  3. 如果想要灵活指定出父类的T类型,子类也需要变为类模板
/*----------------------------------------------------------------
* 项目: Classical Question
* 作者: Fioman
* 邮箱: geym@hengdingzhineng.com
* 时间: 2022/3/22
* 格言: Talk is cheap,show me the code ^_^
//----------------------------------------------------------------*/

#include <iostream>
using namespace std;
// 类模板与继承
template<class T>
class Base
{
public:
	T m;
};

// class Derived:public Base // 错误,必须要知道父类中的T类型,才能继承给子类
class Derived :public Base<int> // 指定父类的T类型是int类型
{

};

// 如果想要灵活指定父类中的T类型,子类也需要变成模板
template <class T1,class T2>
class Son :public Base<T2>
{
public:
	Son()
	{
		cout << "T1的类型: " << typeid(T1).name() << endl;
		cout << "T2的类型: " << typeid(T2).name() << endl;
		cout << "Base::T的类型: " << typeid(Base<T2>::m).name() << endl;
	}
	T1 obj;
};

void test_01(void)
{
	Derived d;
	Son<int,char> s;
}



int main()
{

	test_01();
	system("pause");
	return 0;
}

结果:

九 类模板成员函数类外实现

  1. 类外实现首先要指定成员函数的类作用域
  2. 然后还要加上模板声明以及显示的指定类模板的类型
/*----------------------------------------------------------------
* 项目: Classical Question
* 作者: Fioman
* 邮箱: geym@hengdingzhineng.com
* 时间: 2022/3/22
* 格言: Talk is cheap,show me the code ^_^
//----------------------------------------------------------------*/

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

template <class T>
class Person
{
public:
	Person(T name); 
	void show_person(void);
public:
	T mName;
};

// 类外实现的时候腰加上模板声明,并且类域那里也要加上模板的声明
template <class T>
Person<T>::Person(T name)
{
	this->mName = name;
}

template <class T>

void Person<T>::show_person(void)
{
	cout << "姓名: " << this->mName << endl;
}

int main()
{


	system("pause");
	return 0;
}

十 类模板分文件编写

① 类模板分文件编写的时候会有什么问题
  1. 我们知道类模板的函数是在编译的时候调用的时候创建的
  2. 分文件编写也就是说头文件是文件声明,cpp文件是文件实现
  3. 并且我们在使用的时候一般都是声明包含头文件,但是如果这样使用类模板,在编译的时候,头文件中并没有定义这个函数,导致这个函数会找不到.
② 解决方案
  1. 包含我们的cpp文件,直接包含源文件,只是这种做法有点不符合常规,一般没有包含源文件这种写法
  2. 就是把分文件编写改成单文件编写,把模板类的声明和实现全部放到一个文件中,起名为.hpp文件,我们约定.hpp文件一般就是类模板文件.使用的时候像包含头文件一样包含这个类模板文件就可以了

十一 类模板和友元

① 类内实现

类内实现比较简单,直接在类内声明友元然后实现即可,跟普通的全局友元函数区别不大

② 类外实现的时候
  1. 首先是需要让编译器知道全局函数的存在
  2. 需要类定义的上方进行定义声明
  3. 并且声明定义的时候需要制定是类模板函数
/*----------------------------------------------------------------
* 项目: Classical Question
* 作者: Fioman
* 邮箱: geym@hengdingzhineng.com
* 时间: 2022/3/22
* 格言: Talk is cheap,show me the code ^_^
//----------------------------------------------------------------*/
#include <iostream>
using namespace std;
#include <string>
template <class T1, class T2>
class Person; // 首先是声明Person类

template <class T1, class T2>
void show_person_02(Person<T1,T2>p)
{
	// 实现的是模板函数
	cout << "姓名: " << p.mName << " 年龄: " << p.mAge << endl;
}


template <class T1,class T2>
class Person
{
public:
	Person(T1 name, T2 age)
	{
		this->mName = name;
		this->mAge = age;
	}

	// 友元的类内实现
	friend void show_person(const Person<T1,T2> p)
	{
		cout << "姓名: " << p.mName << " 年龄: " << p.mAge << endl;
	}

	// 友元的类外实现,声明的时候加上空模板参数,代表这个函数是类模板函数
	friend void show_person_02<>(Person<T1,T2> p);
private:
	T1 mName;
	T2 mAge;
};

void test_01(void)
{
	Person<string, int> p1("Tom", 10);
	show_person(p1);
	show_person_02(p1); // 类外实现的全局友元函数
}

int main()
{
	test_01();

	system("pause");
	return 0;
}

十二 类模板案例

① 案例描述

实现一个通用的数组类

  1. 可以对内置数据类型以及自定义数据类型进行存储
  2. 将数组中的数据存储到堆区
  3. 构造函数中可以传入数组的数量
  4. 提供对应的拷贝构造函数以及operrator=方式浅拷贝问题
  5. 提供尾插法和尾删法对数组中的数据进行增加和删除
  6. 可以通过下标的方式访问数组中的元素
  7. 可以获取数组中当前元素的个数和数组的容量
② 设计的思路

在这里插入图片描述

③ 编码实现
/*----------------------------------------------------------------
* 项目: Classical Question
* 作者: Fioman
* 邮箱: geym@hengdingzhineng.com
* 时间: 2022/3/22
* 格言: Talk is cheap,show me the code ^_^
//----------------------------------------------------------------*/
#pragma once
#include <iostream>
using namespace std;

template <class T>
class MyArray
{
public:
	// 有参构造 参数 容量
	MyArray(int capacity)
	{
		cout << "MyArray:: 有参构造调用!" << endl;
		this->mCapacity = capacity;
		this->mSize = 0;
		this->pAddress = new T[this->mCapacity];
	}


	// 拷贝构造
	MyArray(const MyArray &arr)
	{
		cout << "MyArray:: 拷贝构造调用!" << endl;
		this->mCapacity = arr.mCapacity;
		this->mSize = arr.mSize;
		// this->pAddress = arr.pAddress 浅拷贝,错误

		// 将arr中的数据全部拷贝过来,深拷贝就是把之前的内容复制过来进行赋值
		for (int i = 0; i < this->mSize; i++)
		{
			this->pAddress[i] = arr.pAddress[i];
		}
	}

	// operator= 防止浅拷贝的问题
	MyArray &operator=(const MyArray &arr)
	{
		cout << "MyArray:: 的赋值运算符函数被调用!" << endl;
		// 先判断原来的堆区是否有数据,如果有先释放
		if (this->pAddress != NULL)
		{
			delete[] this->pAddress;
			this->pAddress = NULL;
			this->mCapacity = 0;
			this->mSize = 0;
		}

		// 深拷贝
		this->mCapacity = arr.mCapacity;
		this->mSize = arr.mSize;
		this->pAddress = new T[arr.mCapacity];

		return *this;
	}

	// 尾插法
	void push_back(const T &val)
	{
		// 判断荣浪是否等于大小
		if (this->mCapacity == this->mSize)
		{
			return;
		}
		// 在数组的末尾插入数据
		this->pAddress[this->mSize] = val;
		this->mSize++; // 更新数组大小
	}
		

	// 尾部删除
	void pop_back()
	{
		if (this->mSize == 0)
		{
			return;
		}
		this->mSize--;
	}

	// 通过下标的方式访问数组的元素

	T& operator[](int index)
	{
		return this->pAddress[index];
	}

	// 返回数组的容量
	int get_capacity(void)
	{
		return this->mCapacity;
	}

	// 返回数组大小
	int get_size(void)
	{
		return this->mSize;
	}


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

private:
	T *pAddress; // 指针指向堆区开辟的真实数组
	int mCapacity; // 容量
	int mSize; // 数组大小
};

测试代码

/*----------------------------------------------------------------
* 项目: Classical Question
* 作者: Fioman
* 邮箱: geym@hengdingzhineng.com
* 时间: 2022/3/22
* 格言: Talk is cheap,show me the code ^_^
//----------------------------------------------------------------*/

#include <iostream>
#include "myarray.hpp"
using namespace std;

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

void test_01(void)
{
	MyArray <int> arr(5);
	// 尾部插入法插入数据
	for (int i = 0; i < 5; i++)
	{
		arr.push_back(i);
	}

	// 打印数组
	print_arr(arr);

	// 从尾部删除一个数据
	arr.pop_back();
	print_arr(arr); 

	// 最后返回数组的大小和容量
	cout << "数组容量: " << arr.get_capacity() << " 数组的大小: " << arr.get_size() << endl;
}

int main()
{
	test_01();
	system("pause");
	return 0;
}

结果:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值