3.5函数模板

 

模板以template关键字和一个形参表开头

参数至少是有一个模板类型

 

 1 #include <iostream>
 2 using namespace std;
 3 
 4 //T通用数据类型
 5 template <typename T>
 6 T MAX(T *p, const int n)
 7 {
 8     T maxdata(p[0]);
 9 
10     for (int i = 0; i < n; i++)
11     {
12         if (maxdata < p[i])
13         {
14             maxdata = p[i];
15         }
16     }
17 
18     return maxdata;
19 }
20 
21 void main()
22 {
23     int a[10] = { 1,2,3,4,5,6,7,8,9,10 };
24     double b[10] = { 1,2,3,4,5,6,7,8,9,10 };
25 
26     std::cout << MAX(a, 10) << std::endl;
27     std::cout << MAX(b, 10) << std::endl;
28 
29     system("pause");
30 }

 

函数参数不允许使用自动变量

 

//error C3533: 参数不能为包含“auto”的类型

 

 1 #include <iostream>
 2 using namespace std;
 3 
 4 int putnum(auto num)//error C3533: 参数不能为包含“auto”的类型
 5 {
 6 
 7 }
 8 
 9 void main()
10 {
11 
12     system("pause");
13 }

 

函数模板中可以使用inline

 

 1 #include <iostream>
 2 using namespace std;
 3 
 4 template <class T>
 5 inline T getX3(T x)
 6 {
 7     return x*x*x;
 8 }
 9 
10 void main()
11 {
12     std::cout << getX3(1 + 2) << std::endl;//27
13 
14     system("pause");
15 }

 

函数模板根据类型覆盖

//模板为空,明确类型
template <>
void swap1(info &info1, info &info2)
{
std::cout << "特有函数模板" << std::endl;
info temp = info1;
info1 = info2;
info2 = temp;
}

不写上T

 

 1 #include <iostream>
 2 using namespace std;
 3 
 4 //函数模板实现通用,可以根据自有数据类型,进行优化
 5 //结构体可以直接赋值
 6 //所有成员都是公有的类型可以赋值
 7 
 8 struct info
 9 {
10     char name[100];
11     double db;
12     int data;
13 };
14 
15 template <typename T>
16 void swap1(T &a, T &b)
17 {
18     std::cout << "通用函数模板" << std::endl;
19     T temp = a;
20     a = b;
21     b = temp;
22 }
23 
24 //模板为空,明确类型
25 template <>
26 void swap1(info &info1, info &info2)
27 {
28     std::cout << "特有函数模板" << std::endl;
29     info temp = info1;
30     info1 = info2;
31     info2 = temp;
32 }
33 
34 void main()
35 {
36     info info1 = { "hello",20.9,10 };
37     info info2 = { "world",9.2,1 };
38 
39     swap1(info1, info2);//交换两个结构体
40 
41     std::cout << info1.name << " " << info1.db << " " << info1.data << std::endl;
42     std::cout << info2.name << " " << info2.db << " " << info2.data << std::endl;
43 
44     system("pause");
45 }

 

//如果类有私有成员变量,不可以用大括号初始化

//类的对象之间默认是可以直接赋值

//类、结构体都有一个默认赋值操作=浅拷贝

//深拷贝用得最多,函数模板的覆盖

 

 1 #define _CRT_SECURE_NO_WARNINGS
 2 #include <iostream>
 3 using namespace std;
 4 
 5 //如果类有私有成员变量,不可以用大括号初始化
 6 //类的对象之间默认是可以直接赋值
 7 //类、结构体都有一个默认赋值操作=浅拷贝
 8 //深拷贝用得最多,函数模板的覆盖
 9 
10 class info
11 {
12 private:
13     int num;
14 public:
15     char name[100];
16     char *p;
17     int data;    
18     void set(int X)
19     {
20         this->num = X;
21     }
22     int get()
23     {
24         return this->num;
25     }
26 };
27 
28 template <typename T>
29 void swap1(T &a, T &b)
30 {
31     std::cout << "通用函数模板" << std::endl;
32     T temp = a;
33     a = b;
34     b = temp;
35 }
36 
37 //模板为空,明确类型
38 template <>
39 void swap1(info &info1, info &info2)
40 {
41     std::cout << "特有函数模板" << std::endl;
42     info temp = info1;
43     info1 = info2;
44     info2 = temp;
45 }
46 
47 //函数,对一个对象进行深拷贝,需要自己函数模板重载
48 
49 void main()
50 {
51     info info1;
52     info info2;
53 
54     std::strcpy(info1.name, "hello");
55     std::strcpy(info2.name, "world");
56     info1.p = new char[10];
57     std::strcpy(info1.name, "info1.p");
58     info2.p = new char[10];
59     std::strcpy(info2.name, "info2.p");
60     info1.data = 102;
61     info2.data = 201;
62     info1.set(89);
63     info2.set(98);
64 
65     swap1(info1, info2);
66 
67     std::cout << info1.name << " " << info1.p << info1.data << " " << info1.get() << " " << std::endl;
68     std::cout << info2.name << " " << info1.p << info2.data << " " << info2.get() << " " << std::endl;
69 
70     system("pause");
71 }

 

//函数模板可以对类型进行优化重载,根据类型会覆盖

//如果仍然要使用模板函数,需要实例化

 

显式比较准则

函数模板名<模板参数>(参数列表)

 

add<int>(a, b);//T add,实例化

add<int>(db1, db2);//T add,实例化

add<double>(db1, db2);//T add,实例化

 

 1 #include <iostream>
 2 using namespace std;
 3 
 4 //函数模板可以对类型进行优化重载,根据类型会覆盖
 5 //如果仍然要使用模板函数,需要实例化
 6 
 7 template <class T>//函数模板
 8 T add(T a, T b)
 9 {
10     std::cout << "T add" << std::endl;
11     return a + b;
12 }
13 
14 int add(int a, int b)//一般函数
15 {
16     std::cout << "int add" << std::endl;
17     return a + b;
18 }
19 
20 void main()
21 {
22     int a(10), b(20);
23 
24     double db1(10.9), db2(10.8);
25 
26     add(a, b);//int add
27 
28     add(db1, db2);//T add
29 
30     add<int>(a, b);//T add,实例化
31 
32     add<int>(db1, db2);//T add,实例化
33 
34     add<double>(db1, db2);//T add,实例化
35 
36     system("pause");
37 }

 

函数可变参数通用类型,函数模板

 

//通用可变参数模板

//可处理不限定个数的参数,处理不同类型

 

//根据不同的需求,采用不同的设计

//设计可以修改原来的数据的,不要加上const,要引用,void showall(const &value, Args &...args)

//设计可以修改副本,不要const,不要引用,void showall(T value, Args...args)

//设计不可以修改原来的数据,且不能修改副本void showall(const T value, const Args...args)

//设计引用原来的数据,但不可以修改void showall(const T &value, const Args &...args)

 

 1 #include <iostream>
 2 using namespace std;
 3 
 4 //通用可变参数模板
 5 //可处理不限定个数的参数,处理不同类型
 6 
 7 void showall()//空函数,必须保留,作用:接口作用,最后结束递归
 8 {
 9 
10 }
11 
12 //根据不同的需求,采用不同的设计
13 //设计可以修改原来的数据的,不要加上const,要引用,void showall(const &value, Args &...args)
14 //设计可以修改副本,不要const,不要引用,void showall(T value, Args...args)
15 //设计不可以修改原来的数据,且不能修改副本void showall(const T value, const Args...args)
16 //设计引用原来的数据,但不可以修改void showall(const T &value, const Args &...args)
17 
18 template <typename T, typename...Args>
19 void showall(const T &value, const Args &...args)
20 {
21     std::cout << value << std::endl;
22     showall(args...);//继续传递,递归
23     std::cout << std::endl;
24 }
25 
26 void main()
27 {
28     int num1(10), num2(9), num3(11);
29 
30     double db1(10.8), db2(10.9);
31 
32     char str[40] = "hello";
33 
34     char ch = 'A';
35     
36     showall(num1);
37 
38     showall(num1, num2, num3);
39 
40     showall(db1, db2, num1, ch);
41 
42     showall(db1, db2, num1, ch, str);
43 
44     system("pause");
45 }

 

函数模板重载,array数组作为参数

 

 1 #include <iostream>
 2 #include <array>
 3 using namespace std;
 4 
 5 template <typename T>
 6 void showarray(std::array<T, 10> myarray, int n)//对象数组
 7 {
 8     std::cout << "对象数组" << std::endl;
 9     for (int i = 0; i < n; i++)
10     {
11         std::cout << myarray[i] << " ";
12     }
13     std::cout << std::endl;
14 }
15 
16 template <typename T>
17 void showarray(std::array<T *, 10> myarray, int n)//指针数组
18 {
19     std::cout << "指针数组" << std::endl;
20     for (int i = 0; i < n; i++)
21     {
22         std::cout << *myarray[i] << " ";
23     }
24     std::cout << std::endl;
25 }
26 
27 void main()
28 {
29     std::array<int, 10>intarray = { 1,2,3,4,5,6,7,8,9,10 };//创建一个数组,数组的元素类型是int
30 
31     std::array<int *, 10>pintarray;//创建一个数组,数组的元素类型是int *
32 
33     std::array<int **, 10>ppintarray;//创建一个数组,数组的元素类型是int **
34 
35     for (int i = 0; i < 10; i++)
36     {
37         pintarray[i] = &intarray[i];//赋值
38     }
39 
40     for (int i = 0; i < 10; i++)
41     {
42         ppintarray[i] = &pintarray[i];//赋值
43     }
44 
45     showarray(intarray, 10);//对象数组
46 
47     showarray(pintarray, 10);//指针数组
48 
49     showarray(ppintarray, 10);//指针数组
50 
51     system("pause");
52 }

 

面试:

typename与class区别

关键字typename作为类型前的标识符号

 

1 template <class T>
2 class MyClass
3 {
4     typename T::SubType * ptr;
5     //typename指出SubType是T中定义的一个类型,因此ptr是一个指向T::SubType的指针
6     //如果不加上typename,表达式被认为是T中的静态成员SubType和ptr的乘积
7 };

 

C++的一般规则是,除了以typename修饰以外,template内的任何标识符号都被视为一个值value,而非一个类型type

typename的第二个作用:在模板声明中替换关键字class

 

template <typename T>
class MyClass;

 

软件工程规范,用typename,不用class

 

转载于:https://www.cnblogs.com/denggelin/p/5648632.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值