【C++模板编程初探:从泛型思维到实战运用】

你好,这里是新人 Sunfor

这篇是我最近对于C++模板编程初阶的学习心得和错题整理
有任何错误欢迎指正,欢迎交流!
会持续更新,希望对你有所帮助,我们一起学习,一起进步

前言

C++模板是泛型编程的基石,它让代码具备“一写多用”的超能力
通过模板,我们可以编写与数据类型无关的通用代码,既能提升开发效率,又能确保类型安全,本文将带你深入模板的底层逻辑,并通过实战案例掌握其核心用法

一、模板核心概念

1.1 为什么需要模板?

在之前类和对象的学习内容中,我们了解到函数重载,这对比C语言的重命名已经方便不少,但是一些重载的函数,逻辑是十分类似的,我们反复写相似的代码也会浪费程序编写效率,这个时候就需要用到模板

void Swap(int& left, int& right)
{
	int temp = left;
	left = right;
	right = temp;
}

void Swap(double& left, double& right)
{
	double temp = left;
	left = right;
	right = temp;
}

//......

如果我们使用模板,便有以下几个优点

  • 代码复用:一套代码适配多种类型
  • 类型安全:编译期类型检查
  • 性能无损:无运行时的开销

在这里插入图片描述
模板be like:
在这里插入图片描述

1.2 什么是泛型编程?

编写与 类型无关的通用代码,是代码复用的一种手段,模板是泛型编程的基础

二、函数模板

2.1 函数模板的概念

函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本

2.2 函数模板的定义和使用

template<typename T>
T Add(T a, T b)
{
	return a + b;
}

int main()
{
	cout << Add(3, 4) << endl;
	cout << Add(2.5, 3.6) << endl;
	
	//不允许:类型不明确
	//cout << Add(3, 4.4) << endl;

	return 0;
}

typename 是用来定义模板的参数关键字,也可以使用 class

2.3 函数模板的工作原理

  • 编译器实例化:编译器根据调用类型生成具体函数
  • 隐式实例化:根据参数自动推导类型
  • 显示实例化:手动指定模板参数

在这里插入图片描述
函数模板是一个蓝图,它本身不是函数,是编译器用使用方法产生特定具体类型函数的模具,其实模板就是把我们本身需要做的事情丢给了编译器去做

2.4 隐式实例化vs显示实例化

//隐式实例化
template<typename T>
T Add(T a, T b)
{
	return a + b;
}

int main()
{
	int a1 = 10, a2 = 20;
	double b1 = 10.1, b2 = 20.2;

	Add(a1, a2);
	Add(b1, b2);

	Add(a1, (int)b2);//强制类型转换成int

	return 0;
}
//显式实例化
int main(void)
{
	int a = 10;
	double b = 20.2;

	Add<int>(a, b);
	return 0;
}

三、类模板

3.1 类模板的基础语法

template<class T>
class MyArray//模板名
{
//类内成员定义
public:
	MyArray(int size) :_size(size)
	{
		_data = new T[size];
	}

	~MyArray()
	{
		delete[] _data;
	}

	T& operator[](int index)
	{
		return _data[index];
	}

private:
	T* _data;
	int _size;
};

MyArray<int> intArr(10);
MyArray<string> strArr(5);

注意:模板不建议声明和定义分离到两个文件.h和.cpp 可能会出现链接错误

3.2 综合实战

//通用链表
template<typename T>
class LinkedList
{
private:
	struct Node
	{
		T data;
		Node* next;
		//构造函数        初始化列表
		Node(const T& val):data(val),next(nullptr){}
	};

	Node* _head;

public:
	LinkedList():_head(nullptr){}

	void PushFront(const T& val)
	{
		Node* newNode = new Node(val);
		newNode->next = _head;
		_head = newNode;
	}

	void PrintAll()const
	{
		Node* curr = _head;
		while (curr)
		{
			cout << curr->data << "->";
			curr = curr->next;
		}
		cout << "NULL" << endl;
	}

	~LinkedList()
	{
		while (_head)
		{
			Node* temp = _head;
			_head = _head->next;
			delete temp;
		}
	}
};

LinkedList<int> intList;
intList.PushFront(10);
intList.PushFront(20);

LinkedList<string> strList;
strList.PushFront("Hello");
strList.PushFront("World");

四、模板使用的注意事项

  • 编译期特性
    模板代码需要放在头文件中
    模板错误通常在实例化时才会暴露
  • 类型限制
template<typename T>
T Max(T a, T b) {
   return (a > b) ? a : b;  // 要求T必须支持>操作符
}
  • 命名约定
    模板参数通常使用T, U, V等大写字母
    复杂场景使用描述性名称:
template<typename ElementType>
class Container { /*...*/ };

后记

模板是C++赋予开发者的“代码模具”,它让泛型思维照进现实,从此类型不再是创意的枷锁。从简单的Swap函数到复杂的STL容器,模板的魅力在于:用更抽象的代码,表达更普适的逻辑。但这才只是起点——模板元编程、STL等进阶技术,将为你打开编译期计算的新维度。保持好奇心,下面我们将进入STL的学习,探索如何利用STLt提升效率,让你的C++技能更上一层楼~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值