# C++之函数模板与类模板

Java、C/C++ 专栏收录该内容
14 篇文章 0 订阅

# 函数模板的引入

int& max(int& a, int& b)
{
return (a < b)? b : a;
}

double& max(double& a, double& b)
{
return (a < b)? b : a;
}

float& max(float& a, float& b)
{
return (a < b)? b : a;
}

template<typename T>
T& mymax(T& a, T& b)
{
cout<<__PRETTY_FUNCTION__<<endl;
return (a < b)? b : a;
}

int ia = 1, ib = 2;
mymax(ia, ib);

T& mymax(T&, T&) [with T = int]

float fa = 1, fb = 2;
double da = 1, db = 2;
mymax(fa, fb);
mymax(da, db);

T& mymax(T&, T&) [with T = float]
T& mymax(T&, T&) [with T = double]

# 其隐式转换

template<typename T>
T& mymax(T& a, T& b)
{
cout<<__PRETTY_FUNCTION__<<endl;
return (a < b)? b : a;
}

{
}

int main(int argc, char **argv)
{

int a = 1;
double b = 2.1;
mymax(a, b);

return 0;
}

template<typename T>
const T& mymax(const T& a, const T& b)
{
cout<<__PRETTY_FUNCTION__<<endl;
return (a < b)? b : a;
}

int main(int argc, char **argv)
{
int ia = 1;
int ib = 2;
mymax(ia, ib);

return 0;
}

const T& mymax(const T&, const T&) [with T = int]

template<typename T>
const T& mymax(const T& a, const T& b)
{
cout<<__PRETTY_FUNCTION__<<endl;
return (a < b)? b : a;
}

template<typename T>
const T* mymax2(const T* a, const T* b)
{
cout<<__PRETTY_FUNCTION__<<endl;
return (a < b)? b : a;
}

int main(int argc, char **argv)
{
char a[]="ab";
char b[]="cd";

mymax(a, b);
mymax2(a, b);

return 0;
}


const T& mymax(const T&, const T&) [with T = char [3]]
const T* mymax2(const T*, const T*) [with T = char]

	char a2[]="abc";
char b2[]="cd";

mymax(a2, b2);
mymax2(a2, b2);

template<typename T>
void test_func(T f)
{
cout<<__PRETTY_FUNCTION__<<endl;
}

int f1(int a, int b)
{
return 0;
}

int main(int argc, char **argv)
{

test_func(f1);
test_func(&f1);

return 0;
}

void test_func(T) [with T = int (*)(int, int)]
void test_func(T) [with T = int (*)(int, int)]

# 函数模板重载

template<typename T>
const T& mymax(const T& a, const T& b)
{
cout<<"1: "<<__PRETTY_FUNCTION__<<endl;
return (a < b)? b : a;
}

template<typename T>
const T& mymax(T& a, T& b)
{
cout<<"2: "<<__PRETTY_FUNCTION__<<endl;
return (a < b)? b : a;
}

const int& mymax(int& a, int& b)
{
cout<<"3: "<<__PRETTY_FUNCTION__<<endl;
return (a < b)? b : a;
}

int main(int argc, char **argv)
{
int ia = 1;
int ib = 2;

cout<<mymax(ia, ib)<<endl;
return 0;
}

3: const int& mymax(int&, int&)
2

• 先列出候选函数，包括普通函数、参数推导成功的模板函数

• 这些候选函数，根据“类型转换”来排序(注意：模板函数只支持有限的类型转换)

• 如果某个候选函数的参数，跟调用时传入的参数更匹配，则选择此候选函数

• 如果这些候选函数的参数匹配度相同(如果只有一个非模板函数，则选择它；如果只有模板函数，则选择“更特化”的模板函数；否则，最后导致“二义性”错误(ambiguous))

1. 第一个模板函数：mymax(const int &, const int &);第二个模板函数：mymax(int &, int &);第三个普通函数：mymax(int &, int &);
2. 根据参数转换排序，调用时第一个模板函数需要转换排第二，第二模板函数和第三普通函数并列第一
3. 选择"更匹配"的函数
4. 匹配度相同，首先选择普通函数，对于多个模板函数，选择"更特化"的，否则出现二义性错误，因此选择的是普通函数

template<typename T>
const T mymax(T a, T b)
{
cout<<"4: "<<__PRETTY_FUNCTION__<<endl;
return (a < b)? b : a;
}


#if 0
const int& mymax(int& a, int& b)
{
cout<<"3: "<<__PRETTY_FUNCTION__<<endl;
return (a < b)? b : a;
}
#endif

1. 第一个模板函数：mymax(const int &, const int &);第二个模板函数：mymax(int &, int &);第四个模板函数：mymax(int , int);
2. 根据参数转换排序，调用时第一个模板函数需要转换排第二，第二和第四个模板函数并列第一
3. 选择"更匹配"的函数
4. 匹配度相同，首先选择普通函数，对于多个模板函数，选择"更特化"的，否则出现二义性错误，因此对于二和四模板出现了二义性错误

template<typename T>
const T& mymax(const T& a, const T& b)
{
cout<<"1: "<<__PRETTY_FUNCTION__<<endl;
return (a < b)? b : a;
}

template<typename T>
const T& mymax(T& a, T& b)
{
cout<<"2: "<<__PRETTY_FUNCTION__<<endl;
return (a < b)? b : a;
}

const int& mymax(int& a, int& b)
{
cout<<"3: "<<__PRETTY_FUNCTION__<<endl;
return (a < b)? b : a;
}

int main(int argc, char **argv)
{
int ia = 1;
int ib = 2;
int *p1=&ia;
int *p2=&ib;

cout<<mymax(p1, p2)<<endl;
return 0;
}


2: const T& mymax(T&, T&) [with T = int*]
0x7ffc9a8d6d94

1. 第一个模板函数：mymax(const int *&, const int *&);第二个模板函数：mymax(int *&, int *&);第三个普通函数参数不匹配
2. 根据参数转换排序，调用时第二个模板函数不需要转换，而第一个模板需要转换，因此选择第二个

template<typename T>
const T mymax(T * a, T* b)
{
cout<<"4: "<<__PRETTY_FUNCTION__<<endl;
return (*a < *b)? *b : *a;
}

4: const T mymax(T*, T*) [with T = int]
2

1. 第一个模板函数：mymax(const int *&, const int *&);第二个模板函数：mymax(int *&, int *&);第三个普通函数参数不匹配;第四个模板函数：mymax(int *, int *)
2. 根据参数转换排序，调用时第二和第四个模板函数不需要转换，而第一个模板需要转换，第二和第四个模板函数并列第一
3. 第二个和第四个都匹配
4. 它们都是模板函数，选择出"更特化"的（更特殊、更具体和更细化），对于第二个模板函数mymax(T&, T&)，T可以是int或者int*，而对于第四个模板函数参数只能是指针，因此T只能int，所以第四个更细化，因此选择第四个模板函数

template<typename T>
const T mymax(const T * a, const T* b)//这里加上了const
{
cout<<"4: "<<__PRETTY_FUNCTION__<<endl;
return (*a < *b)? *b : *a;
}

2: const T& mymax(T&, T&) [with T = int*]
0x7ffc58a121c4

1. 第一个模板函数：mymax(const int *&, const int *&);第二个模板函数：mymax(int *&, int *&);第三个普通函数参数不匹配;第四个模板函数：mymax(const int *, const int *)
2. 根据参数转换排序，调用时第一和第四个模板函数需要转换，因此选择第二函数模板

template<typename T>
const T& mymax(const T& a, const T& b)
{
cout<<"1: "<<__PRETTY_FUNCTION__<<endl;
return (a < b)? b : a;
}

#if 0
template<typename T>
const T& mymax(T& a, T& b)
{
cout<<"2: "<<__PRETTY_FUNCTION__<<endl;
return (a < b)? b : a;
}
#endif

const int& mymax(int& a, int& b)
{
cout<<"3: "<<__PRETTY_FUNCTION__<<endl;
return (a < b)? b : a;
}

template<typename T>
const T mymax(const T * a, const T* b)
{
cout<<"4: "<<__PRETTY_FUNCTION__<<endl;
return (*a < *b)? *b : *a;
}

1: const T& mymax(const T&, const T&) [with T = int*]
0x7fff9132c1f4

1. 第一个模板函数：mymax(const int *&, const int *&);第三个普通函数参数不匹配;第四个模板函数：mymax(const int *, const int *)
2. 根据参数转换排序，调用时第一和第四个模板函数需要转换并列第一
3. 对于模板一mymax(const T&, const T&)，const修饰的是T，若T为int *，则表示const (int *)&，举例'int *q = &a;const (int *)p = q;"，无法通过p修改q，但是p所指向内容可修改，对于模板四来说，若T为int，则指针所指向的内容不可修改，因此选择第一个模板函数

template<typename T>
const T& mymax(const T& a, const T& b)
{
cout<<"1: "<<__PRETTY_FUNCTION__<<endl;
return (a < b)? b : a;
}

char* mymax(char* a, char* b)
{
cout<<"3: "<<__PRETTY_FUNCTION__<<endl;
return strcmp(a, b) < 0? b : a;
}

template<typename T>
const T mymax(T * a, T* b)
{
cout<<"4: "<<__PRETTY_FUNCTION__<<endl;
return (*a < *b)? *b : *a;
}

int main(int argc, char **argv)
{
char *str1="hello";
char *str2="Hellod";

cout<<mymax(str1, str2)<<endl;
return 0;
}


3: char* mymax(char*, char*)
hello

# 类模板

1. 声明
template<typeclass T>
class AAA{
/* 使用T表示某种类型，比如: */
private:
T obj;
public:
void test_func(T& t);
.....
};

2. 定义
template<typeclass T>
void AAA<T>::test_func(T& t)  ....

## 引入

template<typename T>
class AAA {
private:
T t;
public:
void test_func(const T &t);
void print(void);
};

template<typename T> void AAA<T>::test_func(const T &t)
{
this->t = t;
}

template<typename T>
void AAA<T>::print(void)
{
cout<<t<<endl;
}

int main(int argc, char **argv)
{
AAA<int> a;

a.test_func(1);
a.print();

AAA<double> b;

b.test_func(1.23);
b.print();

return 0;
}

1
1.23

## 定做

1. 声明
template<>
class AAA<int>{
......
public:
void test(void);
};

2. 定义
void AAA<int>::test(void) ...

template<>   //这样写法：订制    类似重载
class AAA<int> {
public:
void test_func_int(const int & t)
{
cout<<t<<endl;
}
void print_int(void);
};

void AAA<int>::print_int(void)
{
cout<<"for test"<<endl;
}


1
for test
1.23

• 1
点赞
• 3
评论
• 1
收藏
• 一键三连
• 扫一扫，分享海报

07-18 1万+
12-02 3933

07-18 69
08-06 8349
05-22 2654
10-26 301
12-29 403
10-11
06-21 1304
12-12 735
05-02 140
04-22 548
09-07 50
07-04 4万+