day34-c++模板

day34-c++模板

一、c++模板简介

1.1 模板的概念

模板的概念是,我们可以定义一个函数或类的框架,但是不指定具体的数据类型,而是用一个占位符(如T)来表示。当我们使用模板时,编译器会根据我们传入的实际类型,生成对应的函数或类的代码。这样,我们就可以避免重复编写相同逻辑的代码,提高代码的复用性和可维护性。

1.2 模板的作用

它可以让我们实现泛型编程(generic programming),即编写与数据类型无关的代码。泛型编程的优点是,它可以提高代码的效率和灵活性,减少错误和冗余,增加代码的可读性和可扩展性。例如,我们可以使用模板来实现一个通用的排序函数,它可以对任何类型的数组进行排序,而不需要为每种类型都写一个专门的排序函数。

1.3 模板的使用场景

当我们需要对不同类型的数据进行相同或类似的操作时,我们可以考虑使用模板。例如,我们可以使用模板来实现一些常用的数据结构(如链表,栈,队列等),它们可以存储任何类型的数据。我们也可以使用模板来实现一些算法(如排序,查找,最大值等),它们可以处理任何类型的数据。

1.4 模板的分类

模板的分类有两种:函数模板和类模板。 函数模板是指定义一个通用的函数,它可以根据不同的参数类型生成不同的函数代码。类模板是指定义一个通用的类,它可以根据不同的参数类型生成不同的类代码。函数模板和类模板都可以有多个参数类型,也可以有默认参数类型。函数模板和类模板都遵循一些语法规则,例如,在定义和使用模板时都要加上template关键字,在使用模板时都要加上尖括号(<>)来指定参数类型等。




二、c++模板定义

模板的定义使用了关键字template,后面跟一个或多个模板参数,用尖括号<>括起来。模板参数可以是类型参数,也可以是非类型参数,如整数或枚举常量。例如,下面是一个简单的模板函数的定义:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

#include <iostream>
using namespace std;

//定义函数模板add
template <typename T> //声明类型可以用typename也可以用class
T add(T a, T b){
return a+b;
}
int main(void){

cout<<add(1,2)<<endl; //根据实参类型自动匹配类型T为int
cout<<add(3.14,2.2)<<endl;
int d = add(3.8,2.9); //根据返回值类型适配类型T为double还是int
cout<<d<<endl;
//cout<<add(3,2.9)<<endl; //编译错误,有两种类型int和double,无法匹配类型T
cout<<add<int>(3,2.9)<<endl; //显示指定T为int
return 0;
}



三、c++模板使用

多参数时可以设置为 template <typename T,int x>,下面是用模板类创建的数组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <iostream>
#include <assert.h>
using namespace std;

template <typename T,int len>
class Array {
public:
Array(T val);
~Array();
T getval(const int ) const;
void setval(const int ,const T);
private:
T *buffer;
};

template <typename T,int len>
Array<T,len>::Array(T val) {
buffer = new T[len];
assert(buffer != NULL); //assert是一个宏定义,不是函数1。它用于检查程序中的条件是否为真。如果条件为假,程序会终止运行,并输出错误信息,包括断言的表达式,源文件名和行号
for (int i = 0; i < len; i++) {
buffer[i] = val;
}
}

template <typename T,int len>
Array<T,len>::~Array() {
delete [] buffer;
}

template <typename T,int len>
T Array<T,len>::getval(const int pos) const {
return buffer[pos];
}

template <typename T,int len>
void Array<T,len>::setval(const int pos,const T val) {
buffer[pos] = val;
}



int main(void){
Array<int , 10> a(0);
a.setval(0,1);
a.setval(1,2);
cout<< a.getval(0) << endl;
cout<< a.getval(1) << endl;
return 0;
}





四、c++友员模板函数

友员模板函数是将模板函数声明为类的友员函数的一种方法。友员模板函数可以访问类的私有成员和保护成员,同时也可以根据不同的类型参数生成不同的函数实例。友员模板函数可以实现一些特定的功能,例如重载运算符,比较不同类型的对象,或者实现多态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
using namespace std;

// 定义一个模板类 Complex,表示复数
template <typename T>
class Complex {
private:
T real; // 实部
T imag; // 虚部
public:
// 构造函数,可以用两个参数或一个参数初始化
Complex(T r = 0, T i = 0) : real(r), imag(i) {}
// 获取实部的值
T getReal() const { return real; }
// 获取虚部的值
T getImag() const { return imag; }
// 定义一个友员模板函数,用于实现+的操作符重载
template <typename U>
friend Complex<U> operator+(const Complex<U>& a, const Complex<U>& b);
};

// 友员模板函数的实现,返回两个复数相加的结果
template <typename U>
Complex<U> operator+(const Complex<U>& a, const Complex<U>& b) {
return Complex<U>(a.getReal() + b.getReal(), a.getImag() + b.getImag());
}

// 测试代码
#include <iostream>
using namespace std;

int main() {
// 创建两个 int 类型的复数对象
Complex<int> c1(1, 2);
Complex<int> c2(3, 4);
// 使用+操作符重载,输出两个复数相加的结果
Complex<int> c3 = c1 + c2;
cout << c3.getReal() << " + " << c3.getImag() << "i" << endl; // 4 + 6i
return 0;
}

再来个例子;

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// 声明一个非类型参数化的函数模板
template <typename T, typename U>
void show(T x, U y);

// 定义一个模板类
template <class T>
class C {
private:
T data;
public:
C(const T& d) : data(d) {}
// 说明一个非类型参数化的函数模板为友员,并在非类型参数前加上typename关键字
template <typename U, typename V>
friend void show(U x, V y);
};

// 定义一个非类型参数化的函数模板
template <typename T, typename U>
void show(T x, U y) {
std::cout << x << " " << y << std::endl;
}

int main() {
C<int> c(10);
// 调用友员函数时,指定非类型参数的类型
show<C<int>, int>(c, 20);
return 0;
}
Donate
  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.
  • Copyrights © 2020-2024 nakano-mahiro
  • Visitors: | Views:

请我喝杯咖啡吧~

支付宝
微信