模板(c++)part1

本文介绍了C++中的模板编程,包括模板的基本使用、函数模板的匹配规则、模板实例化以及类模板的应用,强调了模板在处理不同类型参数时的匹配和实例化过程。
摘要由CSDN通过智能技术生成

目录

1.模板

1.1模板基本使用

1.2.模板实例化

1.3函数模板的匹配规则

2.类模板


!!!!!!!目前更新到这,后面再更新模板的其他内容,本文章只是第一部分,第二部分等后面我再写!!!!

1模板

1.1模板基本使用

template<typename T>
void swap(T& left, T& right)
{
	T temp = left;
	left = right;
	right = temp;
}

int main()
{
	int a = 2, b = 3;
	double a1 = 2.1, b1 = 3.1;
	swap(a, b);
	swap(a1, b1);
	return 0;
}
auto不能用在函数参数上,而void*也难以解决自定义类型,所以c++这里又出现了
个模板,用来解决类似的问题。像上面,我们将交换函数用这种方式写,就可以让内置和自定义都能
放进去。
template是关键字,typename可以用class替代,但不能用struct替代
template<typename T1,typename T2,typename T3,typename T4>

注意,T1,T2可以是一样的类型,比如函数参数是T1& x,T2& y 。我们传可以都穿int,最后T1和T2就都会是int类型。

 像上面的例子,每次调用不同类型,本质上是调用了不同的函数,编译器自身麻烦点,每次都生成个函数来用,但我们只管传就行。

1.2.模板实例化

template<typename T>
T swap(const T& left, const T& right)
{
    return left+right;
}

int main()
{
	int a = 2, b = 3;
	double a1 = 2.1, b1 = 3.1;
	swap(a, a1);
	swap(b, b1);
	return 0;
}
这个情况,模板参数只有一个T,我们传两个不同类型的参数给函数,
编译器无法确认T到底是什么类型,这样就会报错。
我们可以通过给更多的模板参数,函数的参数也用不同的模板参数

还有就是在传参的时候做改变,
T add( T& left,  T& right)
{
	return left + right;
}

int main()
{
	int a = 2, b = 3;
	double a1 = 2.1, b1 = 3.1;
	int g=add(a, b);
	g = add(a, (int)a1);
	cout << g << endl;
	return 0;
}
这时候可以用两种,一个是强转,像上面的一样。一种就是add<int>(a,a1);
也就是显示实例化
但这样还是会报错,为什么呢,因为函数参数我们用了引用,但这样的话,这两种方法本质上都是让传递的参数适应函数模板,并且这两种方法都是产生了,a1都是进行了类型转换,转换后产生的临时变量再传参,但是引用一般不支持临时变量的引用,所以上面的方法必须还得对函数的参数进行改变,如下:
T add( const T& left,  const T& right)//const加引用,才支持临时变量
{
	return left + right;
}

int main()
{
	int a = 2, b = 3;
	double a1 = 2.1, b1 = 3.1;
	int g=add(a, b);
	g = add(a, (int)a1);
	cout << g << endl;
	return 0;
}

而显示实例化,一般是针对模板函数的参数里面没有模板参数,用上面的例子的话,就是add函数的参数里面没有T类型,而是用在了函数体里面。

1.3函数模板的匹配规则

int Add(double left, double right)
{
 return left + right;
}
template<class T>
T Add(T left, T right)
{
 return left + right;
}
void Test()
{
 Add(1, 2); // 与非模板函数匹配,编译器不需要特化
 Add<double>(1, 2); // 调用编译器特化的Add版本
}
非模板函数与同名模板函数可以同时存在。
 Add(1, 2)这句调用第一个函数,因为对于编译器来说会省下一个实例化模板的操作
但如果 Add<double>(1, 2);的话,就会强制让编译器实例化模板函数。

int Add(int left, int right)
{
 return left + right;
}
template<class T1, class T2>
T1 Add(T1 left, T2 right)
{
 return left + right;
}
int main()
{
    Add(1,2);这里会直接调用非模板函数Add,因为类型完全匹配
    Add(1,2.0);//这里,如果没有模板函数,那么也是可以传参的,只是会进行隐式类型转换。
    //但这里有函数模板,那么编译器就会选择实例化函数模板,产生一个更加匹配的函数来接收参数
    return 0;
}
注意!!
函数模板不支持自动类型转换,普通函数支持

2.类模板

 关于类模板,先看下面的代码

class aaa
{
public:
	aaa()
	{
		b = 10;
	}
private:
	int  b;
};

int main()
{
	aaa* a = new aaa;
	return 0;
}
这样这个类里面b是固定的int类型,我们如果想让b存别的类型,就得cv一下,再写个别的类型的
但通过类模板,比如
template<typename T>
class aaa
{
public:
	aaa(T& b)
	{
		_b = b;
	}
private:
	T  _b;
};

int main()
{
	aaa<int> a;
	return 0;
}
通过实例化,我们传什么类型,就生成什么类型的类。
实例化之后的才是一个类,上面那个是类模板

如果类模板里声明一个函数,类模板外定义函数,那么在类模板外定义的时候,要先加个

template<typename T>(具体不一定这样,但是重点是加模板参数列表)在函数定义的上面

template<typename T>
class aaa
{
public:
	aaa(T& b);
private:
	T  _b;
};

template <class T>
aaa<T>::aaa(T& b)
{
	//.....
}

声明和定义必须在同个文件。

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值