【带你吃透C++】 —— 函数模板与类模板

#include<iostream>

using namespace std;

//模板
// C语言为什么不支持模板,因为它不支持泛型编程(例如C++中的模板),C语言中的宏,void *指针 ,_Generic关键字有类似的作用,但相比模板,就是小巫见大巫了
// 原来C语言还可以这样实现“泛型编程”->https://mp.weixin.qq.com/s?src=11&timestamp=1642823699&ver=3573&signature=C1gIeJfQl9FWyg*P4fYaQ*9liVKteLsBsQ-RL37QJUb6U8aj1qRm07iDfreC2*y6ylgsSDFSF8WiU1EY8ItJFI8KabK9YbYSysfl5kjvhiXCuwCRiVTuxxt1d7qaz-1o&new=1
// 
//函数模板
//类模板

//template<class T>
//template<class T1,class T2,class T3>
//template<typename T>

//一.函数模板

//如何实现:模板会自动推演,推演T的具体类型是什么,然后实例化生成具体的函数,彼此的地址也是不同的
template<class T>
void Swap(T& x1, T& x2)
{
    
    
	T tmp = x1;
	x1 = x2;
	x2 = tmp;
}
int main()
{
    
    
	int a = 2, b = 5;

	double m = 8.1, n = 3.2;

	char c1 = 'A', c2 = 'a';

	Swap(c1, c2);//自动识别类型
	Swap(a, b);//自动识别类型

	//C++库自带swap函数模板,直接用
	swap(m,n);
	cout << m << " " << n << endl;
	
	
	cout << a << " " << b << endl;
	cout << c1 << " " << c2 << endl;
	
	
	return 0;
}


//用不同类型的参数使用函数模板时,称为函数模板的实例化。模板参数实例化分为:隐式实例化和显式实例
//化。

//1. 隐式实例化:让编译器根据实参推演模板参数的实际类型

template<class T>
T Add(const T& left, const T& right)
{
    
    
	return left + right;
}
int main()
{
    
    
	int a1 = 10, a2 = 20;
	double d1 = 10.1, d2 = 20.2;
	cout<<Add(a1, a2)<<endl;
	cout << Add(d1, d2)<< endl;

	//cout << Add(a1,d2) << endl;//错误
	//注意:在模板中,编译器一般不会进行类型转换操作,因为一旦转化出问题,编译器就需要背黑锅
	// 此时有两种处理方式:
	
	//1. 用户自己来强制转化 
	cout << Add(a1,(int)d2) << endl;
	cout << Add((double)a1, d2) << endl;

	//2. 使用显式实例化,在函数名后的<>中指定模板参数的实际类型
	cout <<Add <int>(a1,d2) << endl;
	cout << Add<double>(a1, d2) << endl;
	return 0;
}


//模板参数的匹配原则     完全匹配 > 函数模板 > 需要类型转换

// 专门处理int的加法函数(非函数模板类型)
int Add(int left, int right)
{
    
    
	return left + right;
}
// 通用加法函数(函数模板类型)
template<class T>
T Add(T left, T right)
{
    
    
	return left + right;
}
void Test()
{
    
    
	Add(1, 2); // // 与非函数模板类型完全匹配,不需要函数模板实例化
	Add<int>(1, 2); // 因为使用了显式实例化,所以只能使用函数模板实例化

	
	//两者都可以使用,因为非函数模板类型属于普通函数,普通函数可以隐式地进行自动类型转换
	//但是如果有需要转换匹配的,它会优先选择实例化模板生成
	Add(1.1, 2.3);//选择函数模板类型

}





struct TreeNode
{
    
    
	//
};

//二.类模板

//普通类:类名就是类型
//类模板: 类名不是类型,类型是Stack<T>
template<class T >
class Stack
{
    
    
public:
	Stack(int capacity=4)
		:_a(new T[acpacity])
		,_top(0)
		,_capacity(capacity)
	{
    
    }

	~Stack()
	{
    
    
		dalete[] _a;
		_a = nullptr;
		_top = _capacity = 0;
	}

	// 类里面声明,类外面定义
	//注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。
	void Push(const T& x);

private:
	T* _a;
	int _top;
	int _capacity;
};

//模板不支持把声明写到.h ,定义写到.cpp这种声明和定义分开的方式,会报链接错误 ,原因我们后面讲
//类外面定义
template<class T>//声明
void Stack<T>::Push(const T& x)
{
    
    
	//....
}


int main()
{
    
    
	//类模板的使用都是显示实例化
	Stack<TreeNode*> st1;//TreeNode*
	Stack<int> st2;//int

	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_53306029/article/details/123234515