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> &)" (??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 个 ==========
*/
// 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");
}