越是简单而美好的东西,在落向现实的时候,越会变得面目全非。
这是我自己学习C++的第十篇博客总结。后期我会继续把C++学习笔记开源至博客上。 上一期笔记是关于C++的stack类与queue类知识,没看的同学可以过去看看: 【C++】STL容器---Stack类与Queue类-CSDN博客
https://cloud.tencent.com/developer/article/2502836
模板参数分为类型模板参数和非类型模板参数。 非类型模板参数,就是用一个整形常量作为模板的一个参数,在模板中可将该参数当成整形常量来使用。
#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
using namespace std;
template<class T,size_t N=20>
class Stack
{
private:
T _arr[N];
int _top;
};
int main()
{
Stack<int> s1;//N不传值默认为20
Stack<int, 50> s2;
return 0;
}函数模板不建议使用特化,通常都是将该函数直接给出。 类模板的特化分为全特化和偏特化。 全特化即是将模板参数列表中所有的参数都确定化。 偏特化有以下两种表现方式:将模板参数类表中的一部分参数进行特化;针对模板参数类型进行限制。
#define _crt_secure_no_warnings
#include <iostream>
using namespace std;
//普通类模板
template<class T1, class T2>
class Data
{
public:
Data() { cout << "Data<T1, T2>" << endl; }
private:
T1 _d1;
T2 _d2;
};
//全特化类模板
template<>
class Data<int, char>
{
public:
Data() { cout << "Data<int, char>" << endl; }
private:
int _d1;
char _d2;
};
//偏特化类模板
template<class T1>
class Data <T1,int>
{
public:
Data() { cout << "Data<T1, int>" << endl; }
private:
T1 _d1;
int _d2;
};
//两个参数偏特化为指针类型
template <typename T1, typename T2>
class Data <T1*, T2*>
{
public:
Data() { cout << "Data<T1*, T2*>" << endl; }
private:
T1* _d1;
T2* _d2;
};
//两个参数偏特化为引用类型
template <typename T1, typename T2>
class Data <T1&, T2&>
{
public:
Data(const T1& d1, const T2& d2)
: _d1(d1)
, _d2(d2)
{
cout << "Data<T1&, T2&>" << endl;
}
private:
const T1& _d1;
const T2& _d2;
};- 在**a.cpp**中,编译器看到了**Add模板函数的定义**。
- 在**main.cpp**中,编译器看到了**Add模板函数的调用**。
- 由于模板函数的实例化是在使用时进行的,因此在**a.cpp中并没有为Add<int>和Add<double>实例化具体的函数**。- 在**main.obj**中,编译器知道需要调用**Add<int>**和**Add<double>**。
- 但是,在**a.obj**中,并没有为这些类型实例化的具体函数。
- 因此,**链接器找不到这些函数的地址**,导致链接错误。
解决措施:将模板函数的定义放在头文件中,这样每次包含头文件时都会实例化模板。
模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库因此而产生。 增强了代码的灵活性。
模板会导致代码膨胀问题,也会导致编译时间变长。 出现模板编译错误时,错误信息非常凌乱,不易定位错误。
感谢您花时间阅读这篇文章!如果您对本文有任何疑问、建议或是想要分享您的看法,请不要犹豫,在评论区留下您的宝贵意见。每一次互动都是我前进的动力,您的支持是我最大的鼓励。期待与您的交流,让我们共同成长,探索技术世界的无限可能!