首页 > 编程语言 > 详细

p167-C++提高编程-模板

时间:2021-04-06 21:15:47      阅读:32      评论:0      收藏:0      [点我收藏+]

本阶段主要针对C++泛型编程和STL技术做详细讲解

1模板

模板就是建立通用的模具,大大提高复用性

举例子:

技术分享图片

 

 1.2函数模板

C++另一种编程思想成为泛型编程,主要利用的技术就是模板

C++提供两种模板机制:函数模板和类模板

1.2.1函数模板语法

语法如下:

技术分享图片

 

 代码:

 

 1 #include<iostream>
 2 using namespace std;
 3 
 4 //函数模板
 5 
 6 //交换两个整型函数
 7 void swapInt(int &a, int &b)
 8 {
 9     int temp = a;
10     a = b;
11     b = temp;
12 }
13 
14 //交换两个浮点型函数
15 void swapDouble(double &a, double &b)
16 {
17     double temp = a;
18     a = b;
19     b = temp;
20 }
21 
22 //函数模板
23 template<typename T> //声明一个模板,告诉编译器 后面代码中紧跟着的T不要报错,T是一个通用数据类型
24 void mySwap(T &a, T &b)
25 {
26     T temp = a;
27     a = b;
28     b = temp;
29 }
30 
31 
32 void test01()
33 {
34     int a = 10;
35     int b = 20;
36 
37     //swapInt(a, b);
38     //利用函数模板交换
39     //两种方式使用函数模板
40     //1、自动类型推导
41     //mySwap(a, b);
42 
43     //2、显示指定类型
44     mySwap<int>(a, b);
45 
46     cout << "a = " << a << endl;
47     cout << "b = " << b << endl;
48 
49     double c = 1.1;
50     double d = 2.2;
51     swapDouble(c, d);
52     cout << "c = " << c << endl;
53     cout << "d = " << d << endl;
54 
55 
56 }
57 
58 int main()
59 {
60     test01();
61 
62     //system("pause");
63     return 0;
64 }

类型参数化,提高复用性

两种方法使用:自动类型推导,显示指定

1.2.2函数模板注意事项

注意事项:

自动类型推导,必须推导出已知的数据类型T才可以使用

模板必须确定出T的数据类型,才可以使用

1.2.3函数模板案例

利用函数模板实现一个排序函数,可以对不同数据类型数组进行排序

排序规则 从大到小, 排序算法 选择排序

分别利用char数组和int数组进行测试。

 1 #include<iostream>
 2 using namespace std;
 3 
 4 //实现通用 对数组进行排序的函数
 5 //规则 从大到小
 6 //算法 选择排序
 7 //测试 char 数组、 int 数组
 8 
 9 //交换函数模板
10 template<class T>
11 void mySwap(T&a, T&b)
12 {
13     T temp = a;
14     a = b;
15     b = temp;
16 }
17 
18 
19 //排序算法
20 template<class T>
21 void mySort(T arr[], int len)
22 {
23     for (int i = 0; i < len; i++)
24     {
25         int max = i;//认定最大值的下标
26         for (int j = i + 1; j < len; j++)
27         {
28             //认定的最大值 比 遍历出的数值 要小,说明j下标的元素才是真正的最大值
29             if (arr[max] < arr[j])
30             {
31                 max = j;//更新最大值下标
32             }
33         }
34         if (max != i)
35         {
36             //交换max和i下标的元素,把最大的放到最前面去
37             mySwap(arr[max], arr[i]);
38         }
39     }
40 
41 }
42 
43 //提供打印数组模板
44 template<class T>
45 void printArray(T arr[], int len)
46 {
47     for (int i = 0; i < len; i++)
48     {
49         cout << arr[i] << " ";
50     }
51     cout << endl;
52 }
53 
54 void test01()
55 {
56     //测试char数组
57     char charArr[] = "badcfe";
58     int num = sizeof(charArr) / sizeof(char);
59     mySort(charArr, num);
60     printArray(charArr, num);
61 
62 
63 }
64 void test02()
65 {
66     //测试int数组
67     int intArr[] = { 7,5,1,3,9,2,4,6,8 };
68     int num = sizeof(intArr) / sizeof(int);
69     mySort(intArr, num);
70     printArray(intArr, num);
71 }
72 
73 int main()
74 {
75     //test01();
76     test02();
77 
78 
79     return 0;
80 }

1.2.4普通函数和函数模板的调用区别

  普通函数调用时可以发生自动类型转换(隐式类型转换)

  函数模板使用时,如果利用自动类型推导,不会发生隐式类型转换

  如果利用显示指定类型的方式,可以发生隐式类型转换

 1 #include<iostream>
 2 using namespace std;
 3 
 4 //普通函数与函数模板的区别
 5 
 6 //1、普通函数在调用时可以发生隐式类型转换
 7 //2、函数模板 用自动类型推导,不可以发生隐式类型转换
 8 //3、函数模板 用显示指定类型,可以发生隐式类型转换
 9 
10 //普通函数
11 int myAdd01(int a, int b)
12 {
13     return a + b;
14 }
15 
16 //函数模板
17 template<class T>
18 T myAdd02(T a, T b)
19 {
20     return a + b;
21 }
22 
23 
24 void test01()
25 {
26     int a = 10;
27     int b = 20;
28 
29     char c = c;// a = 97    c = 99
30 
31     cout << myAdd01(a, c) << endl;
32 
33     //自动类型推导 不会发生隐式类型转换
34     //cout << myAdd02(a, c)<< endl;
35 
36     //显示指定类型 会发生隐式类型转换
37     cout << myAdd02<int>(a, c) << endl;
38 
39 
40 }
41 
42 
43 int main()
44 {
45 
46     test01();
47 
48 
49     return 0;
50 }

建议使用显示指定类型的方式,调用函数模板

1.2.5普通函数与函数模板调用规则

调用规则:

技术分享图片

 

 

 1 #include<iostream>
 2 using namespace std;
 3 
 4 //普通函数与函数模板调用规则
 5 //1、如果函数模板和普通函数都可以调用,优先调用普通函数
 6 //2、可以通过空模板参数列表的方式 强制 调用 函数模板
 7 //3、函数模板可以发生函数重载
 8 //4、如果函数模板可以产生更好的匹配,优先调用函数模板
 9 
10 void myPrint(int a, int b)
11 {
12     cout << "调用的普通函数" << endl;
13 }
14 
15 template<class T>
16 void myPrint(T a, T b)
17 {
18     cout << "调用的函数模板" << endl;
19 }
20 
21 template<class T>
22 void myPrint(T a, T b, T c)
23 {
24     cout << "调用重载的函数模板" << endl;
25 }
26 
27 void test01()
28 {
29     int a = 10;
30     int b = 20;
31 
32     //myPrint(a, b);
33 
34     //通过空模板参数列表,强制调用函数模板
35     //myPrint<>(a, b);
36 
37     //myPrint(a, b, 100);
38 
39     //如果函数模板产生更好的匹配,优先调用函数模板
40     char c1 = a;
41     char c2 = b;
42     myPrint(c1, c2);
43 }
44 
45 
46 int main()
47 {
48     test01();
49 
50 
51 
52     return 0;
53 }

既然提供了函数模板,最好不要提供普通函数,容易出现二义性。

1.2.6模板的局限性

 

 

 1 #include<iostream>
 2 using namespace std;
 3 #include<string>
 4 
 5 //模板的局限性
 6 //模板并不是万能的,有些特定的数据类型,需要用具体化方式做特殊实现
 7 
 8 class Person
 9 {
10 public:
11     Person(string name, int age)
12     {
13         this->m_Name = name;
14         this->m_Age = age;
15     }
16 
17     //姓名
18     string m_Name;
19     //年龄
20     int m_Age;
21 };
22 
23 //对比两个数据是否相等的函数
24 template<class T>
25 bool myCompare(T &a, T &b)
26 {
27     if (a == b)
28     {
29         return true;
30     }
31     else
32     {
33         return false;
34     }
35 
36 }
37 
38 
39 //利用具体化的Person的版本实现代码,具体化优先调用
40 template<> bool myCompare(Person &p1, Person &p2)
41 {
42     if (p1.m_Name == p2.m_Name && p1.m_Age == p2.m_Age)
43     {
44         return true;
45     }
46     else
47     {
48         return false;
49     }
50 }
51 
52 void test01()
53 {
54     int a = 10;
55     int b = 20;
56     bool ret = myCompare(a, b);
57 
58     if (ret)
59     {
60         cout << "a == b" << endl;
61     }
62     else
63     {
64         cout << "a != b" << endl;
65     }
66 
67 
68 }
69 
70 void test02()
71 {
72     Person p1("Tom", 10);
73     Person p2("Tom", 11);
74 
75     bool ret = myCompare(p1, p2);
76     if (ret)
77     {
78         cout << "p1 == p2" << endl;
79     }
80     else
81     {
82         cout << "p1 != p2" << endl;
83     }
84 
85 }
86 
87 int main()
88 {
89     //test01();
90     test02();
91 
92 
93 
94     return 0;
95 }

利用具体化模板,可以解决自定义类型通用化

学习模板并不是为了写模板,而是在STL中能够运用系统提供的模板

1.3类模板

技术分享图片

 

 

 1 #include<iostream>
 2 using namespace std;
 3 #include<string>
 4 
 5 //类模板
 6 template<class NameType, class AgeType>
 7 class Person
 8 {
 9 public:
10     Person(NameType name, AgeType age)
11     {
12         this->m_Name = name;
13         this->m_Age = age;
14     }
15 
16     void showPerson()
17     {
18         cout << "name: " << this->m_Name
19             << "\t"
20             << "age: " << this->m_Age << endl;
21     }
22 
23     NameType m_Name;
24     AgeType m_Age;
25 
26 };
27 
28 void test01()
29 {
30     Person<string, int> p1("孙悟空", 999);//模板参数列表 和 实参
31     p1.showPerson();
32 }
33 
34 
35 int main()
36 {
37     test01();
38 
39 
40 
41     return 0;
42 }

 

 

1.3.2类模板与函数模板区别

1.类模板没有自动类型推导

2.类模板在模板参数列表中可以有默认参数

 1 #include<iostream>
 2 using namespace std;
 3 #include<string>
 4 
 5 //类模板与函数模板的区别
 6 template<class NameType, class AgeType = int>
 7 class Person
 8 {
 9 public:
10     Person(NameType name, AgeType age)
11     {
12         this->m_Name = name;
13         this->m_Age = age;
14     }
15 
16     void showPerson()
17     {
18         cout << "name: " << this->m_Name
19             <<"\t"
20             << "age = " << this->m_Age << endl;
21     }
22 
23 
24     NameType m_Name;
25     AgeType m_Age;
26 };
27 
28 //1、类模板没有自动类型推导的使用方式
29 void test01()
30 {
31     //Person p("孙悟空", 1000);//错误,无法用自动类型推导
32 
33     Person<string> p("孙悟空", 1000);//正确,智能用显示指定类型
34 
35     p.showPerson();
36 }
37 //2、类模板在模板参数列表中可以有默认参数
38 void test02()
39 {
40     Person<string, int> p("猪八戒", 999);
41     p.showPerson();
42 
43 }
44 
45 int main()
46 {
47     //test01();
48     test02();
49 
50 
51     return 0;
52 }

 

1.3.3类模板中成员函数创建时机

 1 #include<iostream>
 2 using namespace std;
 3 
 4 //类模板中成员函数创建时机
 5 //类模板中成员函数在调用时才去创建
 6 class Person1
 7 {
 8 public:
 9     void showPerson1()
10     {
11         cout << "Person1 show" << endl;
12     }
13 };
14 
15 class Person2
16 {
17 public:
18     void showPerson2()
19     {
20         cout << "Person2 show" << endl;
21     }
22 };
23 
24 template<class T>
25 class MyClass
26 {
27 public:
28     T obj;
29 
30     //类模板中的成员函数
31     void func1()
32     {
33         obj.showPerson1();
34     }
35     void func2()
36     {
37         obj.showPerson2();
38     }
39 
40 };
41 
42 
43 void test01()
44 {
45     MyClass<Person2>m;
46     //m.func1();
47     m.func2();
48 }
49 
50 int main()
51 {
52     test01();
53 
54 
55     return 0;
56 }

类模板中的成员函数并不是一开始就能创建,而是在调用的时候才创建出来。

1.3.4类模板对象做函数参数

技术分享图片

 

 

 1 #include<iostream>
 2 using namespace std;
 3 #include<string>
 4 
 5 //类模板对象做函数参数
 6 template<class T1, class T2>
 7 class Person
 8 {
 9 public:
10     Person(T1 name, T2 age)
11     {
12         this->m_Name = name;
13         this->m_Age = age;
14     }
15 
16     void showPerson()
17     {
18         cout << "姓名: " << this->m_Name
19             <<"\t"
20             << "年龄: " << this->m_Age << endl;
21     }
22 
23     T1 m_Name;
24     T2 m_Age;
25 };
26 //1、指定传入类型
27 void printPerson1(Person<string, int> &p)
28 {
29     p.showPerson();
30 }
31 
32 void test01()
33 {
34     Person<string, int> p("孙悟空", 100);
35 
36     printPerson1(p);
37 }
38 
39 
40 //2、参数模板化
41 template<class T1,class T2>
42 void printPerson2(Person<T1, T2> &p)
43 {
44     p.showPerson();
45     cout << "T1的类型为: " << typeid(T1).name() << endl;
46     cout << "T2的类型为: " << typeid(T2).name() << endl;
47 
48 }
49 
50 void test02()
51 {
52     Person<string, int> p("猪八戒", 90);
53 
54     printPerson2(p);
55 
56 }
57 
58 
59 //3、整个类模板化
60 template<class T>
61 void printPerson3(T &p)
62 {
63     p.showPerson();
64     cout << "T的数据类型为:" << typeid(T).name() << endl;
65 
66 }
67 
68 
69 void test03()
70 {
71     Person<string, int> p("唐僧", 30);
72     printPerson3(p);
73 }
74 
75 
76 int main()
77 {
78     //test01();
79     //test02();
80     test03();
81 
82 
83     return 0;
84 }

三种传递方式

实际开发中最常用的是  指定传入类型;

其他两种,实际上是函数模板配合类模板

 

1.3.5类模板与继承

技术分享图片

 

p167-C++提高编程-模板

原文:https://www.cnblogs.com/zlh-1024powr/p/14623154.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!