cpp拾遗——模板
1. 模板函数
1.1 示例
#include <iostream>
using namespace std;
template <typename T>
void myswap(T &a, T &b)
{
T c;
c = a;
a = b;
b = c;
}
template <typename T>
void mysort(T *arr, int len)
{
int i, j;
bool is_order = false;
for (i = 0; i < len && is_order == false; i++) {
is_order = true;
for (j = len-1; j > i; j--) {
if (arr[j] < arr[j - 1]) {
myswap<T>(arr[j], arr[j-1]);
is_order = false;
}
}
}
}
template <typename T>
void myprint(T *arr, int len)
{
int i;
for (i = 0; i < len; i++)
cout << arr[i] << " ";
cout << endl;
}
template <typename T>
void test(T *arr, int len)
{
cout << "before sort:" << endl;
myprint<T>(arr, len);
mysort<T>(arr, len);
cout << "after sort:" << endl;
myprint<T>(arr, len);
cout << endl;
}
int main()
{
int iarr[] = { 3, 6, 1, 2, 9, 3, 7};
char carr[] = "581694";
test<int>(iarr, sizeof(iarr)/sizeof(*iarr));
test<char>(carr, sizeof(carr)/sizeof(*carr) - 1);
return 0;
}
1.2 普通函数和模板函数
- 普通函数可以进行隐式类型转换,模板函数必须严格类型匹配
- 当普通函数和函数模板都符合调用时,优先使用普通函数
- 如果要优先调用模板函数,可以用空类型参数, test<>();
- 如果模板函数能产生更好的匹配则优先使用模板函数。
1.3 函数模板的本质
test(iarr, sizeof(iarr)/sizeof(*iarr));
1266: 48 8d 45 d0 lea -0x30(%rbp),%rax
126a: be 07 00 00 00 mov $0x7,%esi
126f: 48 89 c7 mov %rax,%rdi
1272: e8 92 00 00 00 callq 1309 <_Z4testIiEvPT_i>
test(carr, sizeof(carr)/sizeof(*carr) - 1);
1277: 48 8d 45 f1 lea -0xf(%rbp),%rax
127b: be 06 00 00 00 mov $0x6,%esi
1280: 48 89 c7 mov %rax,%rdi
1283: e8 30 01 00 00 callq 13b8 <_Z4testIcEvPT_i>
cpp编译器根据函数调用,使用的类型,帮用户生成的对应的函数,
如 int类型的test为 _Z4testIiEvPT_i , char 类型的test为_Z4testIcEvPT_i。
2. 类模板
2.1 意义
template <typename T1, typename T2>
class T{
private:
T1 a;
T2 b;
};
函数模板,让算法可以模板化,
由于类的属性类型可以参数化,类模板让容器可以模板化。
2.2 类模板与派生
template <typename T1>
class A{
private:
T1 a;
};
class AA:public A<int> {
};
template <typename T1>
class AA2:public A<T1> {
};
模板类可以派生出具体类,也可以派生模板类
3. 示例
#include <iostream>
#include <assert.h>
using namespace std;
template <typename T>
class array_t;
template <typename T>
ostream &operator<< (ostream &out, array_t<T> &a);
template <typename T>
class array_t {
friend ostream &operator<< <T>(ostream &out, array_t &a);
public:
array_t(int len);
array_t();
array_t(array_t<T> &a);
T & operator[](int i);
array_t<T> &operator=(array_t<T> &a);
~array_t();
private:
T *data;
int len;
};
template <typename T>
array_t<T> &array_t<T>::operator=(array_t<T> &a)
{
if (data)
delete [] data;
len = a.len;
data = new T [len * sizeof(T)];
for (int i = 0; i < len; i++)
data[i] = a.data[i];
return *this;
}
template <typename T>
array_t<T>::array_t(int len) {
this->len = len;
data = new T [len];
}
template <typename T>
array_t<T>::array_t() {
len = 0;
data = NULL;
}
template <typename T>
array_t<T>::array_t(array_t<T> &a) {
len = a.len;
data = new T [len];
for (int i = 0; i < len; i++)
data[i] = a.data[i];
}
template <typename T>
T & array_t<T>::operator[](int i) {
assert(i < len);
return data[i];
}
template <typename T>
array_t<T>::~array_t() {
if (data)
delete [] data;
}
template <typename T>
ostream &operator<< (ostream &out, array_t<T> &a) {
for (int i = 0; i < a.len; i++)
out << a.data[i] << " ";
return out;
}
void test()
{
array_t<int> int_arr(10);
for (int i = 0; i < 10; i++)
int_arr[i] = i;
cout << int_arr << endl;
array_t<int> int_arr2 = int_arr;
cout << int_arr2 << endl;
array_t<int> int_arr3;
int_arr3 = int_arr2;
cout << int_arr3 << endl;
}
int main()
{
test();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?