模板
数据类型参数化——模板。模板说明的类属参数必须在函数定义中至少出现一次,函数模板定义由模板说明和函数定义组成。
template <class T1,class T2,class T3> void fun(T1 a , T2 b) { a > b? a:b; } //编译出错,没有用到T3
泛型编程函数的使用方法:
1、自动类型推导
2、具体类型调用
template <typename T> void swap(T& x,T& y) { T mid = x; y = x; x= mid; } void main() { int result = swap(1,2); //自动推导 int result_2 = swap <int> (1,2); //显示调用 }
函数模板遇上函数重载:
函数模板不能完成参数的隐式转换。函数模板严格检查参数类型。
templete <typename T> void myswap(T& x,T& y) { T mid = x; y = x; x= mid; } void main() { int result = swap(1,2); //自动推导 result = swap(1,'a'); //编译出错。 }templete <typename T>
void myswap(T& x,T& y) { T mid = x; y = x; x= mid; } void myswap(int& x,char& y) { int mid = x; y = x; x= mid; }
void main() { int result = myswap(1,2); //自动推导 result = myswap(1,'a'); //编译成立。 }
函数重载可以参与函数模板。
templete <typename T> void myswap(T& x,T& y) { T mid = x; y = x; x= mid; } void myswap(int& x,int& y) { int mid = x; y = x; x= mid; } void main() { int result = myswap(1,2); result = myswap(1,'a'); //编译成立,'a'隐式转换为int类型 }
匹配约定:
首先找重载函数(根据参数类型直接匹配到对应函数),如果没有找到,则考虑模板函数,如果没有匹配到,则考虑隐式转换,再选择调用,隐式转换只能针对普通函数存在(换言之,模板函数不能考虑隐式转换调用)。
所以 上述的 result = myswap(1,2);调用的是 void myswap(int& ,int&);而不是调用模板函数。
如果非要调用模板函数呢?——使用显示调用模板方式:result = myswap<>(1,2); "<>"可以为空。
函数模板的本质:
实际上编译器在函数调用时,会根据参数类型生成支持这种类型的函数,所以在实际调用函数时,只能针对性的调用某一个函数,而不能通过类型转换之后再考虑模板函数调用。
所以:模板函数会经过两次编译,第一次是在编译期时,对模板代码本身进行编译;第二次是在函数调用时,会根据参数类型生成相应的专门针对这种参数类型的函数(有几种情况,将会生成几个函数)。
类模板:类也可参数化。
类模板语法:模板说明+类说明
templete <typename T> class A { public: T getA() { return a; } private: T a; }; void fun(A* p) { cout<< p->getA()<<endl; //编译出错 } void fun(A<int> *p) { cout<< p->getA()<<endl; //编译正确 } void main() { A a1; //编译出错,因为 类中成员变量或成员函数是抽象数据类型——T,并不知道到底是什么 A <int> a2; //编译成立 }
templete <typename T> class A { public: A(int a) { this->a = a; } ~A() { ; } T getA() { return a; } private: T a; }; class B :public A<int> //必须指明继承的父类类型 { public: B(int a,int b) :A<int>(a) //父类带参 { this->b = b; } private: int b; }; void fun(A* p) { cout<< p->getA()<<endl; //编译出错 } void fun_2(A<int> *p) { cout<< p->getA()<<endl; //编译正确 } void fun_3(B* bc) { cout<<bc->getA()<<endl; } void main() { A a1; //编译出错,因为 类中成员变量或成员函数是抽象数据类型——T,并不知道到底是什么 A <int> a2; //编译成立 B b1(1,2); //编译成立 fun_3(&b1); //编译成立 }
类模板遇上友元函数:友元函数在模板类外定义,是通不过的,因为模板类的两次编译问题存在。
templete <class T> class complex { public: complex(T Real=0,T Imag =0); void fun(); friend complex operator+(complex& c1,complex& c2); friend complex operator-(complex& c1,complex& c2) { complex temp(c1.real+c2.real,c1.imag+c2.imag); return temp; }//编译通过,模板类中友元函数的定义放在类中 private: T real,imag; }; template <class T> complex<T>::complex(T Real=0,T Imag=0) { this->real = Real; this->imag = Imag; } template <class T> complex<T> operator+(complex<T> &c1,complex<T> &c2) { complex<T> tmp(c1.real+c2.real,c1.imag+c2.iamg); return tmp; }//模板类中的友元函数在类外定义是通不过的 template <class T> void complex<T>::fun() { cout<<this->real<<this->imag<<endl; } void main() { complex<float> c1(1.0,2.0); complex<float> c2(2.4,3.4); c1.print(); complex<float> c3 = c1+c2; complex<float> c3 = c1-c2; }
类模板遇到static成员:
templete <class T> class complex { public: complex(T Real=0,T Imag =0); void fun(); static int m_a; private: T real,imag; }; int complex:: m_a = 0; template <class T> complex<T>::complex(T Real=0,T Imag=0) { this->real = Real; this->imag = Imag; } template <class T> void complex<T>::fun() { cout<<this->real<<this->imag<<endl; } void main() { complex<int> a1(1,2); complex<int> a2(3,4); complex<int> a3(5,6); complex<float> b1(1.1,2.1); complex<float> b2(1.11,2.11); complex<float> b3(1.111,2.111); }
complex<int>定义对象时,生成一个模板专门针对int类型,所有用该类定义的对象共享该类定义的static int a
complex<float>定义对象时,生成另一个模板专门针对float类型,所有用该类定义的对象共享该类定义的static int a
既然是两个类,那么这里的static也是分开的,初始化时都是一样的。
template <class T> class complex { public: complex(T Real=0,T Imag =0); void fun(); static int m_a; private: T real,imag; }; template <class T> int complex<T>:: m_a = 0; template <class T> complex<T>::complex(T Real=0,T Imag=0) { this->real = Real; this->imag = Imag; } template <class T> void complex<T>::fun() { cout<<this->real<<this->imag<<endl; } void main() { complex<int> a1(1,2); a1.m_a++; cout<<a1.m_a<<endl; complex<int> a2(3,4); a2.m_a++; cout<<a1.m_a<<endl; complex<int> a3(5,6);a3.m_a++; cout<<a1.m_a<<endl; complex<float> b1(1.1,2.1); b1.m_a++; cout<<b1.m_a<<endl; complex<float> b2(1.11,2.11); b2.m_a++; cout<<b2.m_a<<endl; complex<float> b3(1.111,2.111); b3.m_a++; cout<<b3.m_a<<endl; getchar(); }


浙公网安备 33010602011771号