03 黑马C++_泛型编程

本文将接着上文(02 黑马C++_核心编程-CSDN博客),继续更新本人在学习黑马C++过程所整理的笔记(本文序号将继续承接上文)。

本文的使用方法:可以将本文作为一个工具书来使用,当编写程序或者阅读程序遇到不熟悉的知识点的时候,可以用 CTRL+F 按键 搜索关键词,查看该知识点。如:当忘记结构体定义方法,需不需要在括号后加分号,就可以 CTRL+F 搜索 “结构体”关键字,即可跳转到所需内容处。相较于使用 C++ Primer 感觉更加快速、便捷,希望对大家有所帮助。

5.1 函数模板

模板不可以直接使用

5.1.1 基本语法

  • 创建函数模板
template<typename T>
void Swap(T &a, T &b)
{
	T temp = a;
	a = b;
	b = temp;
}
  • 函数模板调用
int a = 16, b = 20;
// 法1:自动类型推导
Swap(a, b);
// 法2:显示指定类型
Swap<int>(a, b);

5.1.2 注意事项

  • 可以用 typename / class
template<class T>    // 可以把 typename 改成 class
// 一般可能函数模板用 typename,类模板用 class
  • 模板必须要确定出 T 的数据类型
template<class T>
void func() { };
// 需要指明 T 的类型
func<int>();

5.1.3 普通函数和函数模版的调用规则

![[Pasted image 20230818163936.png]]

5.1.4 模版的局限性

  • 模板具体化
class Person
{
public:
	string name;
	int age;
};
// 定义函数模板
template<class T>
bool Compare(T& a, T& b)
{
	if (a == b)
		return 1;
	else
		return 0;
}
// 如果使用 Person 数据类型,将会走这个函数
template<> bool Compare(Person& p1, Person& p2)
{
	
}

5.2 类模板

5.2.1 基本语法

template<class NameType, class AgeType>
class Person
{
public:
	Person(NameType name, AgeType age)
	{
		this->age = age;
		this->name = name;
	}
	NameType name;
	AgeType age;
};
Person<string, int> p1("孙悟空", 999);

5.2.2 类模板与函数模板的区别

  • 类模板没有自动类型推导的使用方式
  • 类模板在模板参数列表中可以有默认参数
template<class NameType, class AgeType = int>   // 默认参数写法
class Person
{
public:
	Person(NameType name, AgeType age)
	{
		this->age = age;
		this->name = name;
	}
	NameType name;
	AgeType age;
};
Person<string> p1("孙悟空", 999);       // 可以不写第二个参数 int

5.2.3 类模板中成员函数的调用时机

  • 普通类中的成员函数一开始就可以创建
  • 类模板中的成员函数在调用时才创建

5.2.4 类模板对象做函数参数

  • 三种传入方式
// 指定传入类型
void myPrint(Person<string, int>& p)
{
	cout << p.name << endl;
}

// 参数模板化
template<class T1, class T2>
void myPrint2(Person<T1, T2> &p)
{
	cout << typeid(T1).name() << endl;   // 输出 T1 的数据类型名称
	cout << typeid(T2).name() << endl;   // 输出 T2 的数据类型名称
}

// 整个类模板化
template<class T>
void myPrint3(T& p)
{
	cout << p.name << endl;
}

5.2.5 类模板与继承

  • 如果子类继承的父类是一个类模板,子类在声明时要指出父类的类型
  • 如果想灵活指出父类的类型,子类也需要变为类模板
template<class T>
class Base
{   };

class Son : public Base<int>	// 需要指明父类中 T 的类型
{   };

template<class T1, class T2>
class Son2 : public Base<T2>	// T2指明父类的参数类型
{
public:
	T1 a;						// T1指明子类的参数类型
};

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

  • 需要前面加上 template 定义 和 作用域加上<T1,T2>
template<class T1, class T2>
class Person
{
public:
	Person(T1 name, T2 age);
	T1 name;
	T2 age;
};
// 类外实现
template<class T1, class T2>            // 需要加上类模板定义
Person<T1,T2>::Person(T1 name, T2 age)  // 注意作用域需要加上<T1,T2>
{
	this->age = age;
	this->name = name;
}

5.2.7 类模板分文件编写

![[Pasted image 20230818185021.png]]

问题:类模板中成员函数创建时机是在调用阶段,导致文件编译时链接不到
解决:

  1. 直接包含 .cpp 源文件
  2. 将声明和实现写到同一个文件中,并改后缀名为 .hpp

5.2.8 案例

![[Pasted image 20230818193200.png]]

  • 模板数组的深拷贝拷贝构造重载=
template<class T>
class myArray
{
public:
	// 拷贝构造
	myArray(const myArray& a)
	{
		this->capacity = a.capacity;
		this->size = a.size;
		
		this->arr = new T[a.capacity];    // 在堆区开辟同容量空间
		for (int i = 0; i < a.size; i++)  // 将已有的值赋值过去
			this->arr[i] = a.arr[i];

	}
	
	// 重载 = 号,防止浅拷贝问题
	myArray& operator=(const myArray& a)
	{
		// 需要先判断原来堆区是否有数据,如果有需要先释放
		if (this->arr != NULL) {
			delete[] arr;
			this->arr = NULL;
			this->capacity = 0;
			this->size = 0;
		}
		this->capacity = a.capacity;
		this->size = a.size;
		this->arr = new T[a.capacity];    // 在堆区开辟同容量空间
		for (int i = 0; i < a.size; i++)  // 将已有的值赋值过去
			this->arr[i] = a.arr[i];
	}

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

private:
	T* arr;
	int capacity;
	int size;
};
// 调用
myArray<int> a(5);

至此,C++泛型编程文章已更新完毕,下篇将更新 C++ STL技术。

  • 25
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_小猪沉塘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值