Java中的泛型编程可以极大的提升编程的效率,比如在android中查找一个控件的ID:标准写法为:
TextView tv_text = (TextView)findViewById(R.id.tv_text);
或者:
ImageView iv_img = (ImageView)findViewById(R.id.iv_img);
因为同为查询控件ID,所以上面的写法可以采用泛型编程精简为:
protected final <T extends View> T getView(int id) { return (T) findViewById(id); }
这样在下次使用的时候就可以写成这样:
TextView tv_text = getView(R.id.tv_text);
C++中也有类似的东西,不过名字变了,叫模板(template)。
一.函数模板
例:交换两个相同类型变量的值
原始写法:
//交换 int 变量的值 void Swap(int *a, int *b){ int temp = *a; *a = *b; *b = temp; } //交换 float 变量的值 void Swap(float *a, float *b){ float temp = *a; *a = *b; *b = temp; } //交换 char 变量的值 void Swap(char *a, char *b){ char temp = *a; *a = *b; *b = temp; } //交换 bool 变量的值 void Swap(bool *a, bool *b){ char temp = *a; *a = *b; *b = temp; }
使用模板后的写法:
#include <iostream> using namespace std; template<typename T> void Swap(T *a, T *b){ T temp = *a; *a = *b; *b = temp; } int main(){ //交换 int 变量的值 int n1 = 100, n2 = 200; Swap(&n1, &n2); cout<<n1<<", "<<n2<<endl; //交换 float 变量的值 float f1 = 12.5, f2 = 56.93; Swap(&f1, &f2); cout<<f1<<", "<<f2<<endl; //交换 char 变量的值 char c1 = 'A', c2 = 'B'; Swap(&c1, &c2); cout<<c1<<", "<<c2<<endl; //交换 bool 变量的值 bool b1 = false, b2 = true; Swap(&b1, &b2); cout<<b1<<", "<<b2<<endl; return 0; }
修改成引用:
#include <iostream> using namespace std; template<typename T> void Swap(T &a, T &b){ T temp = a; a = b; b = temp; } int main(){ //交换 int 变量的值 int n1 = 100, n2 = 200; Swap(n1, n2); cout<<n1<<", "<<n2<<endl; //交换 float 变量的值 float f1 = 12.5, f2 = 56.93; Swap(f1, f2); cout<<f1<<", "<<f2<<endl; //交换 char 变量的值 char c1 = 'A', c2 = 'B'; Swap(c1, c2); cout<<c1<<", "<<c2<<endl; //交换 bool 变量的值 bool b1 = false, b2 = true; Swap(b1, b2); cout<<b1<<", "<<b2<<endl; return 0; }
例:求三个数最大值:
#include <iostream> using namespace std; //声明函数模板 template<typename T> T max(T a, T b, T c); int main( ){ //求三个整数的最大值 int i1, i2, i3, i_max; cin >> i1 >> i2 >> i3; i_max = max(i1,i2,i3); cout << "i_max=" << i_max << endl; //求三个浮点数的最大值 double d1, d2, d3, d_max; cin >> d1 >> d2 >> d3; d_max = max(d1,d2,d3); cout << "d_max=" << d_max << endl; //求三个长整型数的最大值 long g1, g2, g3, g_max; cin >> g1 >> g2 >> g3; g_max = max(g1,g2,g3); cout << "g_max=" << g_max << endl; return 0; } //定义函数模板 template<typename T> //模板头,这里不能有分号 T max(T a, T b, T c){ //函数头 T max_num = a; if(b > max_num) max_num = b; if(c > max_num) max_num = c; return max_num; }
运行结果:
12 34 100
i_max=100
73.234 90.2 878.23
d_max=878.23
344 900 1000
g_max=1000
总结一下,函数模板的基本语法为:
template <typename 类型参数1 , typename 类型参数2 , ...> 返回值类型 函数名(形参列表){ //在函数体中可以使用类型参数 }
二.类模板
类模板的声明与函数模板的声明类似:
template<typename 类型参数1 , typename 类型参数2 , …> class 类名{ //TODO: };
示例代码:
#include <iostream> using namespace std; template<class T1, class T2> //这里不能有分号 class Point{ public: Point(T1 x, T2 y): m_x(x), m_y(y){ } public: T1 getX() const; //获取x坐标 void setX(T1 x); //设置x坐标 T2 getY() const; //获取y坐标 void setY(T2 y); //设置y坐标 private: T1 m_x; //x坐标 T2 m_y; //y坐标 }; template<class T1, class T2> //模板头 T1 Point<T1, T2>::getX() const /*函数头*/ { return m_x; } template<class T1, class T2> void Point<T1, T2>::setX(T1 x){ m_x = x; } template<class T1, class T2> T2 Point<T1, T2>::getY() const{ return m_y; } template<class T1, class T2> void Point<T1, T2>::setY(T2 y){ m_y = y; } int main(){ Point<int, int> p1(10, 20); cout<<"x="<<p1.getX()<<", y="<<p1.getY()<<endl; Point<int, char*> p2(10, "东京180度"); cout<<"x="<<p2.getX()<<", y="<<p2.getY()<<endl; Point<char*, char*> *p3 = new Point<char*, char*>("东京180度", "北纬210度"); cout<<"x="<<p3->getX()<<", y="<<p3->getY()<<endl; return 0; }
输出结果:
x=10, y=20
x=10, y=东京180度
x=东京180度, y=北纬210度
注意:
1.在对类模板的成员函数进行定义时,除了 template 关键字后面要指明类型参数,类名 Point 后面也要带上类型参数,只是不加 typename 关键字了
2.类模板在实例化时必须显式地指明数据类型,赋值号两边也要指明具体的数据类型,且要保持一致。