1.泛型编程基础
#include "iostream" using namespace std; void swap(int &a, int &b) { int c; c = a; a = b; b = c; } void swap(float &a, float &b) { float c; c = a; a = b; b = c; } void main() { int a = 1, b = 2; swap(a, b); float a1 = 1, b1 = 2; swap(a1, b1); system("pause"); }
#include "iostream" using namespace std; //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.函数模板加强
#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<num; i++) { for (j = i; j<num; 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<num; 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"); }
3.
函数模板遇上函数重载
函数模板可以像普通函数一样被重载
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.函数模板本质探究:
编译器并不是把函数模板处理成能够处理任意类型的函数
编译器从函数模板通过具体类型产生不同的函数
编译器会对函数模板进行两次编译
在声明的地方对模板代码本身进行编译
在调用的地方对参数替换后的代码进行编译
#include "cstdlib" using namespace std; /* 函数模板的深入理 ― 编译器并不是把函数模板处理成能够处理任意类型的函数 ― 编译器从函数模板通过具体类型产生不同的函数 ― 编译器会对函数模板进行两次编译 ―在声明的地方对模板代码本身进行编译 ―在调用的地方对参数替换后的代码进行编译 */ //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
分析1.s
.file "1.cpp" .lcomm __ZStL8__ioinit, 1, 1 .def ___main;.scl 2;.type 32;.endef .section.rdata, "dr" LC2: .ascii "hello....\0" LC3 : .ascii "pause\0" .text .globl _main .def _main;.scl 2;.type 32;.endef _main : pushl %ebp movl %esp, %ebp andl $ - 16, %esp subl $32, %esp call ___main movl $1, 28(%esp) movl $2, 24(%esp) leal 24(%esp), %eax movl %eax, 4(%esp) leal 28(%esp), %eax movl %eax, (%esp) call __Z5swap2IiEvRT_S1_ //24-49 movl $0x3f800000, %eax movl %eax, 20(%esp) movl $0x40000000, %eax movl %eax, 16(%esp) leal 16(%esp), %eax movl %eax, 4(%esp) leal 20(%esp), %eax movl %eax, (%esp) call __Z5swap2IfEvRT_S1_ //33-69 movl $LC2, 4(%esp) movl $__ZSt4cout, (%esp) 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 ret .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 ret .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 ret .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 ret .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 L5 : leave ret .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 ret .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> &)" ([email protected][email protected]@@[email protected]@Z),该符号在函数 _main 中被引用 1>E:\01-work\09-就业班0415\day16\泛型编程\Debug\泛型编程.exe : fatal error LNK1120: 1 个无法解析的外部命令 ========== 生成: 成功 0 个,失败 1 个,最新 0 个,跳过 0 个 ========== */ // template<class T> // 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 ) ; // } template<typename T> void Complex<T>::print()const { cout << '(' << Real << " , " << Image << ')' << endl; } void main() { Complex<int>c1(1, 2); Complex<int>c2(3, 4); Complex<int>c3 = c1 + c2; c3.print(); system("pause"); }
7.类模板遇上static
#include "iostream" using namespace std; const double pi = 3.14159; template<typename T> class Circle { T radius; static int total; //类模板的静态数据成员 public: Circle(T r = 0) { radius = r; total++; } void Set_Radius(T r) { radius = r; } double Get_Radius() { return radius; } 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; } void main() { Circle<int> A, B; //建立了2个对象 A.Set_Radius(16); cout << "A.Radius = " << A.Get_Radius() << endl; cout << "A.Girth = " << A.Get_Girth() << endl; cout << "A.Area = " << A.Get_Area() << endl; B.Set_Radius(105); cout << "B.radius = " << B.Get_Radius() << endl; cout << "B.Girth=" << B.Get_Girth() << endl; 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"); }
时间: 2024-10-17 14:51:19