C++进阶之函数模板——类模板(一)

1.函数模板

1.1为什么要有函数模板

需求:写n个函数,交换char类型、int类型、double类型变量的值。

案例:

按 Ctrl+C 复制代码

按 Ctrl+C 复制代码

1.2函数模板语法

函数模板定义形式

  template < 类型形式参数表 >

类型形式参数的形式为:

      typename T1 , typename T2 , …… , typename Tn

class T1 , class T2 , …… , class Tn

函数模板调用

myswap<float>(a, b); //显示类型调用

myswap(a, b); //自动数据类型推导

1.3函数模板和模板函数

1.4函数模板做函数参数

#include<iostream> 2 using namespace std; 3 4 /* 5 让你对int行数组 和字符数组排序 6 函数模板本质:类型参数化 7 */ 8 template <typename T, typename T2> 9 int mySort(T *array, int size)10 {11 if (array == NULL)12 {13 return -1;14 }15 for (T2 i =0 ;i<size; i++)16 {17 for (T2 j =i+1; j<size; j++)18 {19 if (array[i] > array[j])20 {21 T temp;22 temp = array[i];23 array[i] = array[j];24 array[j] = temp;25 }26 }27 }28 return 0;29 }30 template <typename T, typename T2>31 int myPrintf(T *array, T2 size)32 {33 for (T2 i = 0; i<size; i++)34 {35 cout << array[i] << endl;36 }37 return 0;38 }39 void main21()40 {41 {//int类型42 int myarray[] = { 22, 33,44, 43, 56, 2, 44, 76 };43 int size = sizeof(myarray) / sizeof(*myarray);44 mySort<int, int>(myarray, size);45 46 printf("排序之后:\n");47 myPrintf<int, int>(myarray, size);48 }49 50 {51 //char类型52 char buf[] = "ggggggghhhhhjjjdfffzzzzvvv";53 int len = strlen(buf);54 mySort<char, int>(buf, len);55 myPrintf<char, int>(buf, len);56 }57 58 system("pause");59 }

你还在为没有学习平台而苦恼吗?你还在为没有学习资料而烦心吗?你还在为没人指导而担忧吗?可以私信小编 C++,为你提供学习的平台和资料。

1.5函数模板遇上函数重载

函数模板和普通函数区别结论:

  (1)函数模板不允许自动类型转化

  (2)普通函数能够进行自动类型转换

函数模板和普通函数在一起,调用规则: 

1 函数模板可以像普通函数一样被重载

2 C++编译器优先考虑普通函数

3 如果函数模板可以产生一个更好的匹配,那么选择模板

4 可以通过空模板实参列表的语法限定编译器只通过模板匹配

以下代码对上面文字进行说明:

案例1:

1 #include <iostream> 2 using namespace std; 3 4 template <typename T> 5 void myswap(T &a, T &b) 6 { 7 T t; 8 t = a; 9 a = b;10 b = t;11 cout<<"myswap 模板函数do"<<endl;12 }13 void myswap(char &a, int &b)14 {15 int t;16 t = a;17 a = b;18 b = t;19 cout<<"myswap 普通函数do"<<endl;20 }21 22 void main()23 {24 char cData = 'a';25 int iData = 2;26 27 //myswap<int>(cData, iData); //结论 函数模板不提供隐式的数据类型转换 必须是严格的匹配28 29 myswap(cData, iData);
30 //myswap(iData, cData);31 32 cout<<"hello..."<<endl;33 system("pause");34 return ;35 }

案例2:

1 #include<iostream> 2 using namespace std; 3 4 //让类型参数化---》方便程序员进行编码 5 //泛型编程 6 //template告诉C++编译器,开始泛型编程,不要随便报错 7 template <typename T> 8 void myswap(T &a, T &b) 9 {10 T c;11 c = a;12 a = b;13 b = c;14 cout << "我是模板函数-----》" << endl;15 }16 void myswap(int a, char c)17 {18 cout << "a:" << "c:" << c << endl;19 cout << "我是普通函数-----》" << endl;20 }21 void main31()22 {23 int a = 10;24 char c = 'z';25 myswap(a,c);//当普通函数调用,可以进行隐式的类型转化26 27 myswap(c, a);28 29 myswap(a, a);//调用函数模板,(本质:类型参数化) 将严格进行类型匹配,不会进行类型转化30 31 }

描述

1.6C++编译器模板机制剖析

思考:为什么函数模板可以和函数重载放在一块。C++编译器是如何提供函数模板机制的?

1 #include<iostream> 2 using namespace std; 3 4 //1.cpp 5 6 //g++ -S 1.cpp -o 1.s 变成汇编语言 7 template <typename T> 8 void myswap(T &a, T &b) 9 {10 T c;11 c = a;12 a = b;13 b = c;14 cout << "hello------" << endl;15 }16 //函数模板的调用,显示类型调用,自动类型推倒17 void main51()18 {19 {20 int x = 10;21 int y = 20;22 myswap<int>(x, y);//函数模板的显示类型调用23 24 25 printf("x:%d y:%d \n", x, y);26 }27 {28 char a = 'a';29 char b = 'b';30 myswap<char>(a, b);//函数模板的显示类型调用31 32 printf("x:%d y:%d \n", a, b);33 }34 35 }36 /*37 原理:38 C++编译器会根据你的调用来产生函数,如果是int型的会产生int型的函数39 ,如果是char会产生,char型的函数,如果有的话,就不会产生了。40 41 C++编译器帮我们写了一个函数,经过两次编译,形成的42 */43 /*44 函数模板机制结论45 编译器并不是把函数模板处理成能够处理任意类的函数46 编译器从函数模板通过具体类型产生不同的函数47 编译器会对函数模板进行两次编译48 在声明的地方对模板代码本身进行编译;在调用的地方对参数替换后的代码进行编译。49 */

首先补充一些知识:

编译器编译原理:

什么是gcc

gcc(GNU C Compiler)编译器的作者是Richard Stallman,也是GNU项目的奠基者。

什么是gcc:gcc是GNU Compiler Collection的缩写。最初是作为C语言的编译器(GNU C Compiler),现在已经支持多种语言了,如C、C++、Java、Pascal、Ada、COBOL语言等。

gcc支持多种硬件平台,甚至对Don Knuth 设计的 MMIX 这类不常见的计算机都提供了完善的支持

gcc主要特征

1)gcc是一个可移植的编译器,支持多种硬件平台

2)gcc不仅仅是个本地编译器,它还能跨平台交叉编译。

3)gcc有多种语言前端,用于解析不同的语言。

4)gcc是按模块化设计的,可以加入新语言和新CPU架构的支持

5)gcc是自由软件

   gcc编译过程

    gcc常用编译选项

预处理(Pre-Processing)

编译(Compiling)

汇编(Assembling)

链接(Linking)

Gcc *.c –o 1exe (总的编译步骤)

Gcc –E 1.c –o 1.i //宏定义 宏展开

Gcc –S 1.i –o 1.s

Gcc –c 1.s –o 1.o

Gcc 1.o –o 1exe

结论:gcc编译工具是一个工具链。。。。

hello程序是一个高级C语言程序,这种形式容易被人读懂。为了在系统上运行hello.c程序,每条C语句都必须转化为低级机器指令。然后将这些指令打包成可执行目标文件格式,并以二进制形式存储器于磁盘中。

选项

作用

-o

产生目标(.i、.s、.o、可执行文件等)

-c

通知gcc取消链接步骤,即编译源码并在最后生成目标文件

-E

只运行C预编译器

-S

告诉编译器产生汇编语言文件后停止编译,产生的汇编语言文件扩展名为.s

-Wall

使gcc对源文件的代码有问题的地方发出警告

-Idir

将dir目录加入搜索头文件的目录路径

-Ldir

将dir目录加入搜索库的目录路径

-llib

链接lib库

-g

在目标文件中嵌入调试信息,以便gdb之类的调试程序调试

1.7函数模板机制结论

编译器并不是把函数模板处理成能够处理任意类的函数

编译器从函数模板通过具体类型产生不同的函数

编译器会对函数模板进行两次编译

在声明的地方对模板代码本身进行编译;在调用的地方对参数替换后的代码进行编译。

你还在为没有学习平台而苦恼吗?你还在为没有学习资料而烦心吗?你还在为没人指导而担忧吗?可以私信小编 C++,为你提供学习的平台和资料。

举报
评论 0