【C/C++学院】(11)泛型编程/函数模板/类模板
2023-09-14 08:57:16 时间
//template关键字告诉c++编译器,现在开始泛型编程
//typename 告诉c++编译器,T为类型(T为类型,可以参数化,int float),你不要乱报错
//类型参数化。。。。。。。
template typename T
void swap2(T a, T b)
T c;
c = a;
a = b;
b = c;
void main()
//泛型编程的调用方式有两种
//自动类型推导
int x = 1, y = 2;
swap2(x, y);
printf("x:%d y:%d \n", x, y);
float x1 = 1.0, y1 = 2.0;
//具体类型调用
swap2 float (x1, y1);
printf("x1:%f y1:%f \n", x1, y1);
system("pause");
2.函数模板加强
函数模板遇上函数重载 函数模板可以像普通函数一样被重载 C++编译器优先考虑普通函数 如果函数模板可以产生一个更好的匹配,那么选择模板 可以通过空模板实参列表的语法限定编译器只通过模板匹配
4.函数模板本质探究: 编译器并不是把函数模板处理成能够处理任意类型的函数 编译器从函数模板通过具体类型产生不同的函数
― 编译器并不是把函数模板处理成能够处理任意类型的函数 ― 编译器从函数模板通过具体类型产生不同的函数 ― 编译器会对函数模板进行两次编译 ―在声明的地方对模板代码本身进行编译 ―在调用的地方对参数替换后的代码进行编译 //template告诉编译器,这里开始进行泛型编程 //typename告诉编译器,类型名称为T 编译器你看到类型T 不要乱报错。。。。 //T为类型,类型参数化而已 template typename T void swap2(T a, T b) T t = a; a = b; b = t; int main() int x = 1; int y = 2; //泛型编程的调用方式分为两种 //自动类型 推导调用 swap2 int (x, y); //printf("\n%d, %d", x, y); float x1 = 1.0; float y1 = 2.0; //具体类 显示调用 swap2 float (x1, y1); //printf("\n%f, %f", x1, y1); cout "hello...." endl; system("pause"); return 0; } g++ -S 1.cpp 生成了1.s
call __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc movl $__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, 4(%esp) movl %eax, (%esp) call __ZNSolsEPFRSoS_E movl $LC3, (%esp) call _system movl $0, %eax leave .section.text$_Z5swap2IiEvRT_S1_, "x" .linkonce discard .globl __Z5swap2IiEvRT_S1_ .def __Z5swap2IiEvRT_S1_;.scl 2;.type 32;.endef __Z5swap2IiEvRT_S1_ : pushl %ebp movl %esp, %ebp subl $16, %esp movl 8(%ebp), %eax movl(%eax), %eax movl %eax, -4(%ebp) movl 12(%ebp), %eax movl(%eax), %edx movl 8(%ebp), %eax movl %edx, (%eax) movl 12(%ebp), %eax movl - 4(%ebp), %edx movl %edx, (%eax) leave .section.text$_Z5swap2IfEvRT_S1_, "x" .linkonce discard .globl __Z5swap2IfEvRT_S1_ .def __Z5swap2IfEvRT_S1_;.scl 2;.type 32;.endef __Z5swap2IfEvRT_S1_ : pushl %ebp movl %esp, %ebp subl $16, %esp movl 8(%ebp), %eax movl(%eax), %eax movl %eax, -4(%ebp) movl 12(%ebp), %eax movl(%eax), %edx movl 8(%ebp), %eax movl %edx, (%eax) movl 12(%ebp), %eax movl - 4(%ebp), %edx movl %edx, (%eax) leave .text .def ___tcf_0;.scl 3;.type 32;.endef ___tcf_0 : pushl %ebp movl %esp, %ebp subl $24, %esp movl $__ZStL8__ioinit, (%esp) call __ZNSt8ios_base4InitD1Ev leave .def __Z41__static_initialization_and_destruction_0ii;.scl 3;.type 32;.endef __Z41__static_initialization_and_destruction_0ii : pushl %ebp movl %esp, %ebp subl $24, %esp cmpl $1, 8(%ebp) jne L5 cmpl $65535, 12(%ebp) jne L5 movl $__ZStL8__ioinit, (%esp) call __ZNSt8ios_base4InitC1Ev movl $___tcf_0, (%esp) call _atexit leave .def __GLOBAL__sub_I_main;.scl 3;.type 32;.endef __GLOBAL__sub_I_main : pushl %ebp movl %esp, %ebp subl $24, %esp movl $65535, 4(%esp) movl $1, (%esp) call __Z41__static_initialization_and_destruction_0ii leave .section.ctors, "w" .align 4 .long __GLOBAL__sub_I_main .def __ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_;.scl 2;.type 32;.endef .def __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc;.scl 2;.type 32;.endef .def __ZNSolsEPFRSoS_E;.scl 2;.type 32;.endef .def _system;.scl 2;.type 32;.endef .def __ZNSt8ios_base4InitD1Ev;.scl 2;.type 32;.endef .def __ZNSt8ios_base4InitC1Ev;.scl 2;.type 32;.endef .def _atexit;.scl 2;.type 32;.endef
5.类模板基础
6.类模板遇上友元函数
【C++要笑着学】泛型编程 | 函数模板 | 函数模板实例化 | 类模板(二) 本章将正式开始介绍C++中的模板,为了能让大家更好地体会到用模板多是件美事!我们将会举例说明,大家可以试着把自己带入到文章中,跟着思路去阅读和思考,真的会很有意思!如果你对网络流行梗有了解,读起来将会更有意思!
【C++要笑着学】泛型编程 | 函数模板 | 函数模板实例化 | 类模板(一) 本章将正式开始介绍C++中的模板,为了能让大家更好地体会到用模板多是件美事!我们将会举例说明,大家可以试着把自己带入到文章中,跟着思路去阅读和思考,真的会很有意思!如果你对网络流行梗有了解,读起来将会更有意思!
2.函数模板加强
#include "iostream" using namespace std; template typename T void sortArray(T *a, int num) int i = 0, j = 0; T tmp; for (i = 0; i i++) for (j = i; j j++) if (a[i] a[j]) tmp = a[i]; a[i] = a[j]; a[j] = tmp; template class T void printfArray(T *a, int num) cout endl; for (int i = 0; i i++) cout a[i] " "; void main() int a[10] = { 1, 3, 4, 5, 2, 3, 44, 6, 3 }; int num = sizeof(a) / sizeof(*a); sortArray int (a, num); printfArray int (a, num); char buf[] = "163addeadfdsafdsaf"; int len = strlen(buf); sortArray char (buf, len); printfArray char (buf, len); system("pause");
函数模板遇上函数重载 函数模板可以像普通函数一样被重载 C++编译器优先考虑普通函数 如果函数模板可以产生一个更好的匹配,那么选择模板 可以通过空模板实参列表的语法限定编译器只通过模板匹配
/* 1 函数模板可以像普通函数一样被重载 2 C++编译器优先考虑普通函数 3 如果函数模板可以产生一个更好的匹配,那么选择模板 4 可以通过空模板实参列表的语法限定编译器只通过模板匹配 函数模板不允许自动类型转化 普通函数能够进行自动类型转换 #include iostream using namespace std; int Max(int a, int b) cout "int Max(int a, int b)" endl; return a b ? a : b; template typename T T Max(T a, T b) cout "T Max(T a, T b)" endl; return a b ? a : b; template typename T T Max(T a, T b, T c) cout "T Max(T a, T b, T c)" endl; return Max(Max(a, b), c); void main() int a = 1; int b = 2; cout Max(a, b) endl; cout Max (a, b) endl; cout Max(3.0, 4.0) endl; cout Max(5.0, 6.0, 7.0) endl; cout Max(a, 100) endl; system("pause"); return;
4.函数模板本质探究: 编译器并不是把函数模板处理成能够处理任意类型的函数 编译器从函数模板通过具体类型产生不同的函数
― 编译器并不是把函数模板处理成能够处理任意类型的函数 ― 编译器从函数模板通过具体类型产生不同的函数 ― 编译器会对函数模板进行两次编译 ―在声明的地方对模板代码本身进行编译 ―在调用的地方对参数替换后的代码进行编译 //template告诉编译器,这里开始进行泛型编程 //typename告诉编译器,类型名称为T 编译器你看到类型T 不要乱报错。。。。 //T为类型,类型参数化而已 template typename T void swap2(T a, T b) T t = a; a = b; b = t; int main() int x = 1; int y = 2; //泛型编程的调用方式分为两种 //自动类型 推导调用 swap2 int (x, y); //printf("\n%d, %d", x, y); float x1 = 1.0; float y1 = 2.0; //具体类 显示调用 swap2 float (x1, y1); //printf("\n%f, %f", x1, y1); cout "hello...." endl; system("pause"); return 0; } g++ -S 1.cpp 生成了1.s
call __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc movl $__ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_, 4(%esp) movl %eax, (%esp) call __ZNSolsEPFRSoS_E movl $LC3, (%esp) call _system movl $0, %eax leave .section.text$_Z5swap2IiEvRT_S1_, "x" .linkonce discard .globl __Z5swap2IiEvRT_S1_ .def __Z5swap2IiEvRT_S1_;.scl 2;.type 32;.endef __Z5swap2IiEvRT_S1_ : pushl %ebp movl %esp, %ebp subl $16, %esp movl 8(%ebp), %eax movl(%eax), %eax movl %eax, -4(%ebp) movl 12(%ebp), %eax movl(%eax), %edx movl 8(%ebp), %eax movl %edx, (%eax) movl 12(%ebp), %eax movl - 4(%ebp), %edx movl %edx, (%eax) leave .section.text$_Z5swap2IfEvRT_S1_, "x" .linkonce discard .globl __Z5swap2IfEvRT_S1_ .def __Z5swap2IfEvRT_S1_;.scl 2;.type 32;.endef __Z5swap2IfEvRT_S1_ : pushl %ebp movl %esp, %ebp subl $16, %esp movl 8(%ebp), %eax movl(%eax), %eax movl %eax, -4(%ebp) movl 12(%ebp), %eax movl(%eax), %edx movl 8(%ebp), %eax movl %edx, (%eax) movl 12(%ebp), %eax movl - 4(%ebp), %edx movl %edx, (%eax) leave .text .def ___tcf_0;.scl 3;.type 32;.endef ___tcf_0 : pushl %ebp movl %esp, %ebp subl $24, %esp movl $__ZStL8__ioinit, (%esp) call __ZNSt8ios_base4InitD1Ev leave .def __Z41__static_initialization_and_destruction_0ii;.scl 3;.type 32;.endef __Z41__static_initialization_and_destruction_0ii : pushl %ebp movl %esp, %ebp subl $24, %esp cmpl $1, 8(%ebp) jne L5 cmpl $65535, 12(%ebp) jne L5 movl $__ZStL8__ioinit, (%esp) call __ZNSt8ios_base4InitC1Ev movl $___tcf_0, (%esp) call _atexit leave .def __GLOBAL__sub_I_main;.scl 3;.type 32;.endef __GLOBAL__sub_I_main : pushl %ebp movl %esp, %ebp subl $24, %esp movl $65535, 4(%esp) movl $1, (%esp) call __Z41__static_initialization_and_destruction_0ii leave .section.ctors, "w" .align 4 .long __GLOBAL__sub_I_main .def __ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_;.scl 2;.type 32;.endef .def __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc;.scl 2;.type 32;.endef .def __ZNSolsEPFRSoS_E;.scl 2;.type 32;.endef .def _system;.scl 2;.type 32;.endef .def __ZNSt8ios_base4InitD1Ev;.scl 2;.type 32;.endef .def __ZNSt8ios_base4InitC1Ev;.scl 2;.type 32;.endef .def _atexit;.scl 2;.type 32;.endef
5.类模板基础
#include iostream using namespace std; //定义一个类模板 template typename T class AA public: AA(T a) this- a = a; void setA(T a) this- a = a; T getA() return this- a protected: private: T a; class BB : public AA int public: //BB(int a, int b) : AA(a) BB(int a, int b) : AA int (a) this- b = b; private: int b; void main() //要把类模板具体成类型后,才能定义变量 AA int a(10); BB b1(1, 2); system("pause"); }
6.类模板遇上友元函数
#include iostream using namespace std; template class T class Complex public: Complex(T r = 0, T i = 0); Complex(T a) { Real = a; Image = 0; } void print() const; //直接在类的内部声明定义,否则编译器报警 friend Complex T operator+(Complex T c1, Complex T c2) T r = c1.Real + c2.Real; T i = c1.Image + c2.Image; return Complex T (r, i); //friend Complex operator- ( const Complex T c1, const Complex T c2 ); //friend Complex operator- ( const Complex T c ); private: T Real, Image; template class T Complex T ::Complex(T r, T i) Real = r; Image = i; "class Complex int __cdecl operator+(class Complex int ,class Complex int )" (??H@YA?AV?$Complex@H@@AAV0@0@Z),该符号在函数 _main 中被引用 1 E:\01-work\09-就业班0415\day16\泛型编程\Debug\泛型编程.exe : fatal error LNK1120: 1 个无法解析的外部命令 ========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ==========
double Get_Girth() { return 2 * pi * radius; } double Get_Area() { return pi * radius * radius; } static int ShowTotal(); //类模板的静态成员函数 template typename T int Circle T ::total = 0; template typename T int Circle T ::ShowTotal() return total;
cout "B.Area = " B.Get_Area() endl; cout "Total1=" Circle int ::ShowTotal() endl; //显示建立的对象数 cout endl; Circle double X(6.23), Y(10.5), Z(25.6); //建立了3个对象 cout "X.Radius = " X.Get_Radius() endl; cout "X.Girth = " X.Get_Girth() endl; cout "X.Area = " X.Get_Area() endl; cout "Y.radius = " Y.Get_Radius() endl; cout "Y.Girth=" Y.Get_Girth() endl; cout "Y.Area = " Y.Get_Area() endl; cout "Z.Girth=" Z.Get_Girth() endl; cout "Z.Area = " Z.Get_Area() endl; cout "Total2=" Circle double ::ShowTotal() endl; //显示建立的对象数 system("pause");
【C++要笑着学】泛型编程 | 函数模板 | 函数模板实例化 | 类模板(二) 本章将正式开始介绍C++中的模板,为了能让大家更好地体会到用模板多是件美事!我们将会举例说明,大家可以试着把自己带入到文章中,跟着思路去阅读和思考,真的会很有意思!如果你对网络流行梗有了解,读起来将会更有意思!
【C++要笑着学】泛型编程 | 函数模板 | 函数模板实例化 | 类模板(一) 本章将正式开始介绍C++中的模板,为了能让大家更好地体会到用模板多是件美事!我们将会举例说明,大家可以试着把自己带入到文章中,跟着思路去阅读和思考,真的会很有意思!如果你对网络流行梗有了解,读起来将会更有意思!
相关文章
- C++学习之路——名字空间与模板
- C++泛型编程,模板(一)函数模板
- EasyC++39,函数模板
- c++关机程序
- 深入理解C++11_c++ string char
- C++中的引用处理
- c++的链表-C++链表
- 数据结构小记【Python/C++版】——B树篇
- 【C++ 语言】面向对象 ( 模板编程 | 函数模板 | 类模板 )
- 【C++修炼之路】7. 模板初阶
- C++STL——vector类与模拟实现
- 【C++】模板进阶
- C++中的标准化工厂—— 模板
- C++11可变参数模板
- C++继承和派生是什么意思(通俗易懂)
- C++函数模板(模板函数)详解
- C++类模板中的静态成员
- C++ unordered_map及其基本结构和特性
- C++ swap函数模板及其用法
- 如何用 C++ 读写文件
- 深入解析C++中的指针数组与指向指针的指针
- 深入解析C++中的mutable关键字
- VC++实现输出GIF到窗体并显示GIF动画的方法
- C++类模板与模板类深入详解
- C++函数模板与类模板实例解析
- C++可变参数的函数与模板实例分析
- C++实现打印1到最大的n位数
- Lua教程(五):C/C++操作Lua数组和字符串示例