实现方式

编译器有差别,在windows中和在linux中的实现方式不同。

在VS 编译器下

在VS编译器下可以这么实现:

test.cpp

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
#include <iostream>

using namespace std;

template<class T>
class Person {
public:
Person(T age, T id);
void show();
template<class T>
friend ostream& operator<<(ostream& os, Person<T>& p);
template<class T>
friend void print_person<T>(Person<T>& p);

private:
T mAge;
T mId;
};

template<class T>
Person<T>::Person(T age, T id) {
this->mAge = age;
this->mId = id;
}

template<class T>
void Person<T>::show() {
cout << "Age: " << mAge << " ID: " << mId << endl;
}

template<class T>
ostream& operator<<(ostream& os, Person<T>& p) {
return os << "Age: " << p.mAge << " ID: " << p.mId << endl;
}

template<class T>
void print_person(Person<T>& p) {
cout << "Age: " << p.mAge << " ID: " << p.mId << endl;
}

int main() {
Person<int> p(20, 5);
cout << p;
return 0;
}

统一编译器

但是gcc编译器会报错,为了统一二者,可以用如下的方式实现,这样在不同的编译器下都能正常运行:

test.cpp

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
#include <iostream>

using namespace std;

// 类外声明
template<class T> class Person;
template<class T> ostream& operator<<(ostream& os, Person<T>& p);
template<class T> void print_person(Person<T>& p);

template<class T>
class Person {
public:
Person(T age, T id);
void show();
// 友元函数要在函数名后面加个<T>
friend ostream& operator<< <T>(ostream& os, Person<T>& p);
friend void print_person<T>(Person<T>& p);
private:
T mAge;
T mId;
};

template<class T>
Person<T>::Person(T age, T id) {
this->mAge = age;
this->mId = id;
}

template<class T>
void Person<T>::show() {
cout << "Age: " << mAge << " ID: " << mId << endl;
}

template<class T>
ostream& operator<<(ostream& os, Person<T>& p) {
return os << "Age: " << p.mAge << " ID: " << p.mId << endl;
}

template<class T>
void print_person(Person<T>& p) {
cout << "Age: " << p.mAge << " ID: " << p.mId << endl;
}

类模板的声明(.h)与定义(.cpp)分离编写

类声明:Person.h:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#pragma once
#include <iostream>

using namespace std;

template<class T>
class Person {
public:
Person(T age, T id);
void show();

private:
T mAge;
T mId;
};

类定义:Person.hpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "Person.h"

template<class T>
Person<T>::Person(T age, T id) {
this->mAge = age;
this->mId = id;
}

template<class T>
void Person<T>::show() {
cout << "Age: " << mAge << " ID: " << mId << endl;
}

// 注意此处,需要显式实例化,以便在main函数中使用Person<int>
template
class Person<int>;

使用:test.cpp

1
2
3
4
5
6
7
8
9
#include "Person.h"

int main(){

Person<int> p(10, 111);
p.show();

return 0;
}

可以看出这种方式需要显式地实例化,并且每当需要新的类型如Person<double>, Person<float>, Person<Student>时都需要挨个添加实例化代码,较为繁琐。因此建议采用下面的这种方式实现。

将类模板声明与定义放在同一个文件里(.hpp)

声明 + 定义:Person.hpp

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
#pragma once
#include <iostream>

using namespace std;

template<class T>
class Person {
public:
Person(T age, T id);
void show();

private:
T mAge;
T mId;
};

template<class T>
Person<T>::Person(T age, T id) {
this->mAge = age;
this->mId = id;
}

template<class T>
void Person<T>::show() {
cout << "Age: " << mAge << " ID: " << mId << endl;
}

使用:test.cpp

1
2
3
4
5
6
7
8
#include "Person.hpp"

int main() {
Person<int> p(10, 209);
p.show();

return 0;
}