C++模板

C++模板

被 palabos 倒逼学 C++。

1 模板:与类型无关的代码

模板让数据,函数的参数,函数的返回值能够是任何类型。模板的声明只能在全局,命名空间或类范围内进行。

1-1 函数模板

一个小例子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream> 
using namespace std;

template <class T>
void sswap(T &a, T &b)
{
T tmp = a;
a = b;
b = tmp;
}

int main()
{

int a = 5;
int b = 4;

sswap(a,b);

cout << "a = " << a << endl;
cout << "b = " << b << endl;

return 0;
}

1-2 类模板: 一个模板栈的例子

定义类模板

类模板只是编译指令,实例化都是在编译期完成的。所以不能单独编译,定义和实现都在同一个文件中,最简单的就是放在头文件中。 Palabos 很多功能是用类模板封装的,所以源代码是一堆头文件。

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
52
53
54
55
56
57
58
59
#ifndef STACKTP_H_
#define STACKTP_H_
template <class Type,int MAX> // 类型参数,非类型参数
class Stack
{
private:
Type items[MAX];
int top;
public:
Stack();
bool isempty();
bool isfull();
bool push(const Type item);
bool pop(Type &item);
};

template <class Type,int MAX>
Stack<Type,MAX>::Stack()
{
top = 0;
}

template <class Type,int MAX>
bool Stack<Type,MAX>::isempty()
{
return top == 0;
}

template <class Type,int MAX>
bool Stack<Type,MAX>::isfull()
{
return top == MAX;
}

template <class Type,int MAX>
bool Stack<Type,MAX>::push(const Type item)
{
if (top < MAX)
{
items[top++] = item;
return true;
}
else
return false;
}

template <class Type,int MAX>
bool Stack<Type,MAX>::pop(Type &item)
{
if (top > 0)
{
item = items[--top];
return true;
}
else
return false;
}

#endif

模板的具体化

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
#include <iostream>
#include <string>
#include <cctype>
#include "stacktp.h"
using namespace std;

int main()
{
Stack<string,3> st; // 传入类型参数和非类型参数
char ch;
string po;
cout << "A: push\nP: pop\nQ: quit\n";
while (cin >> ch && toupper(ch) != 'Q')
{
while (cin.get() != '\n')
continue;
if (!isalpha(ch))
{
cout << "input again:";
continue;
}
switch(ch)
{
case 'A':
case 'a': cout << "Enter: ";
cin >> po;
if (st.isfull())
cout << "stack already full\n";
else
st.push(po);
break;
case 'P':
case 'p': if (st.isempty())
cout << "stack already empty\n";
else {
st.pop(po);
cout << "PO #" << po << " popped\n";
break;
}
}
cout << "A: push\nP: pop\nQ: quit\n";
}
cout << "Bye\n";

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
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
using std::cout;
using std::endl;

template <typename T>
class beta
{
private:
template <typename V> // 模板类作为成员
class hold
{
private:
V val;
public:
hold(V v = 0) : val(v) {}
void show() const { cout << val << endl; }
V Value() const { return val; }
};
hold<T> q; // 成员模板的对象
hold<int> n; // 成员模板的对象
public:
beta( T t, int i) : q(t), n(i) {} // 构造函数这样传递信息
template<typename U> // 函数模板作为成员
U blab(U u, T t) { return (n.Value() + q.Value()) * u / t; }
void Show() const { q.show(); n.show();}
};

int main()
{
beta<double> guy(3.5, 3);
cout << "T was set to double\n";
guy.Show();
cout << "V was set to T, which is double, then V was set to int\n";
cout << guy.blab(10, 2.3) << endl;
cout << "U was set to int\n";
cout << guy.blab(10.0, 2.3) << endl;
cout << "U was set to double\n";
cout << "Done\n";
// std::cin.get();
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
29
30
31
32
33
34
35
36
#include <iostream>
#include "stacktp.h" // 需要用到前面这个头文件
using namespace std;

template <template <class Type,int MAX> class Thing>
// template <class Type,int MAX> class 类型的参数 Thing
class Crab
{
private:
Thing<int,5> s1;
Thing<double,5> s2;
public:
Crab() {};
// assumes the thing class has push() and pop() members
bool push(int a, double x) { return s1.push(a) && s2.push(x); }
bool pop(int & a, double & x){ return s1.pop(a) && s2.pop(x); }
};

int main()
{
Crab<Stack> nebula;
// Stack must match template <typename T> class thing
int ni;
double nb;
cout << "Enter int double pairs, such as 4 3.5 (0 0 to end):\n";
while (cin>> ni >> nb && ni > 0 && nb > 0)
{
if (!nebula.push(ni, nb))
break;
}

while (nebula.pop(ni, nb))
cout << ni << ", " << nb << endl;
cout << "Done.\n";
return 0;
}
作者

缪红林

发布于

2021-06-03

更新于

2021-06-08

许可协议

评论