C++模板编程—学习C++类库的编程基础


课程总目录


文章目录


一、详解函数模板

模板的意义:对类型也可以进行参数化了

cpp 复制代码
// 也可以用template<class T>,但class容易和类混淆,我们都用typename
template<typename T>	// 模板参数列表
bool compare(T a, T b)	// compare是一个函数模板
{
	cout << "template compare" << endl;
	return a > b;
}

/*
调用点实例化出来的模板函数
bool compare<int>(int a, int b)
{
	return a > b;
}

bool compare<double>(double a, double b)
{
	return a > b;
}
*/

int main()
{
	// 函数的调用点
	compare<int>(10, 20);
	compare<double>(10.5, 20.5);

	// 函数模板实参推演
	compare(20, 20); 	 // 还是用的刚才实例化的compare<int>
	// compare(30, 40.5); // 错误,推演不出来是什么类型
	// 解决方法一:template<typename T, typename E>,a和b用两个类型,各推各的
	// 解决方法二:compare<int>(30, 40.5),double强转成int
}

函数模板:不进行编译,因为类型还不知道
模板函数 :在函数调用点,编译器用程序员指定的类型,从原模板实例化一份函数代码出来这就叫做模板函数,这是实例化出来真正需要进行编译的函数 ,因此站在编译器的角度来看,待编译的函数并没有减少,只是我们编写的代码量减少了。

同时,实例化出来的模板函数在.o文件符号表中产生相应的符号,每个函数名的符号只能出现一次

来看看字符串的情况 (模板的特例化)

cpp 复制代码
// 针对compare函数模板,提供const char*类型的特例化版本
template<>	// 要写上
bool compare(const char* a, const char* b)
{
	cout << "compare<const char*>" << endl;
	return strcmp(a, b) > 0;
}
// 模板特化不需要在函数名后面加上类型参数
// 即别写成compare<const char*>

int main()
{
	// 推演T为const char*,字符串 > 代表的是比较两个常量的地址,要用strcmp才能比较字符串的字典顺序
	// 对于某些类型来说,依赖编译器默认实例化的模板代码,代码处理逻辑是错误的
	// 这时候,就需要我们进行模板的特例化了,这不是编译器提供的,而是程序员提供的
	compare("aaa", "bbb");
	compare<const char*>("aaa", "bbb");
	// 这两种写法都是对的
}

当然,非模板函数(普通函数)优先被调用

cpp 复制代码
//非模板函数 - 普通函数
bool compare(const char* a, const char* b)
{
	cout << "normal compare" << endl;
	return strcmp(a, b) > 0;
}

int main()
{
	// 这时候就调用普通函数了,不调用模板函数了
	compare("aaa", "bbb");
	// 调用模板函数
	compare<const char*>("aaa", "bbb");
}

编译器优先把compare处理成函数名字,没有的话,才去找compare模板特例化,如果没有特例化,才进行模板的实例化

分文件编写

模板代码是不能在一个文件中定义,在另一个文件中使用的,否则链接的时候会出现错误

比如在test.cpp中存放模板代码,在main.cpp中声明,这是不可以的,因为声明产生的符号是*UND*,而在test.cpp中只有模板,模板本身是不编译的,没有模板实例化出来的compare<int>等函数,所以不可以

模板代码调用之前,一定要看到模板定义的地方,这样的话,模板才能进行正常的实例化,产生能够被编译器编译的代码。

所以,模板代码都是放在头文件.h当中的,然后在原文件当中直接进行#include包含

模板的非类型参数:

必须是整数类型(整数或者地址/引用都可以)是常量,只能使用,而不能修改

模板不仅可以接受类型参数typename T,还可以接受非类型参数。这些非类型参数可以是整型、指针、引用等。它们在编译时是常量,只能使用,不能修改

示例代码:

cpp 复制代码
template <int N>
class Array {
public:
    int arr[N];
    
    int size() const { return N; }
};

int main() {
    Array<5> myArray; // 创建一个包含5个整数的数组
    cout << "Array size: " << myArray.size() << endl;
    return 0;
}
cpp 复制代码
// 使用模板实现冒泡排序
template <typename T, int N>
void bubbleSort(T* arr) {
	for (int i = N - 1; i >= 1; --i)
	{
		int flag = 0;
		for (int j = 1; j <= i; ++j)
		{
			if (arr[j - 1] > arr[j])
			{
				T temp = arr[j];
				arr[j] = arr[j - 1];
				arr[j - 1] = temp;
				flag = 1;
			}
		}
		if (flag == 0)
			return;
	}
}

int main() {
	int arr[] = { 64, 34, 25, 12, 22, 11, 90 };
	const int size = sizeof(arr) / sizeof(arr[0]);

	// 调用冒泡排序模板函数
	bubbleSort<int, size>(arr);

	cout << "排序后的数组: ";
	for (int i : arr)
		cout << i << " ";
	cout << endl;

	return 0;
}

二、初识类模板

三、理解容器空间配置器allocator的重要性

四、实现C++STL向量容器vector代码

相关推荐
闻缺陷则喜何志丹14 分钟前
【C++动态规划 图论】3243. 新增道路查询后的最短距离 I|1567
c++·算法·动态规划·力扣·图论·最短路·路径
charlie11451419126 分钟前
C++ STL CookBook
开发语言·c++·stl·c++20
小林熬夜学编程37 分钟前
【Linux网络编程】第十四弹---构建功能丰富的HTTP服务器:从状态码处理到服务函数扩展
linux·运维·服务器·c语言·网络·c++·http
倔强的石头1061 小时前
【C++指南】类和对象(九):内部类
开发语言·c++
A懿轩A2 小时前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组
机器视觉知识推荐、就业指导2 小时前
C++设计模式:享元模式 (附文字处理系统中的字符对象案例)
c++
半盏茶香2 小时前
在21世纪的我用C语言探寻世界本质 ——编译和链接(编译环境和运行环境)
c语言·开发语言·c++·算法
Ronin3053 小时前
11.vector的介绍及模拟实现
开发语言·c++
✿ ༺ ོIT技术༻3 小时前
C++11:新特性&右值引用&移动语义
linux·数据结构·c++
字节高级特工3 小时前
【C++】深入剖析默认成员函数3:拷贝构造函数
c语言·c++