C++学习之模板
2015-09-02 21:45
344 查看
C++学习之模板
有关C++模板的概念,详细学过C++的人都应该有所耳闻,其是泛型编程的基础。顾名思义,模板就是相当于一个模子,通过这个模子我们可以做出各种各样的东西,C++模板就是这样的一种工具。之所以要在C++中引入模板,就是为了减少C++程序中代码的重复工作,达到代码的可重用的功能。举一个我们常用的例子,比较两个整型a,b的大小,我们定义一个函数,但是如果比较的是两个浮点型的内,或者还有一个字符型的内?那么我们不是得写三个函数?这样就写了很多重复性的代码,那么我们可不可以把这三个函数或者更多类似的函数写成一个内?答案是肯定的,这就可以用到我们的模板了。C++常用的模板方式有函数模板和类模板,下面我们就分别介绍。一、函数模板
1.类型参数
函数模版在函数定义的时候,我们可以不指定参数变量的具体数据类型,而是在函数调用时,编译器根据传入的参数自动确定数据类型。函数模板可以实现对数据类型的传递和检查。下面是定义一个函数模板的实例:template <class T> T function(T data) { cout<<data; return data; }这里template是我们声明一个模板的关键字,class也可以用typename替换,T就表示了我们的类型参数,当我们实现函数调用时,如果传递的是一个整型数,编译器就把T解释为int,如果是浮点型传入,编译器就把T解释为float,如此,我们不就把一类函数都归结会一个函数了吗?这就是代码的可重用性。当然我们还可以在函数调用的时候直接指出传递的参数类型,就像下面这种格式:
function<int>(a);
另外我们的模板声明也可以指定多种类型参数,比方说我们还可以这样:
template <class T1,class T2>
T1 function(T1 data1,T2 data2) { cout<<data1; cout<<data2; return data; }
2.非类型参数
在函数模板中,我们还可以指定非类型参数,采用显示的类型来进行指定,他表示一个常量值,在实例化一个函数的时候,就用该值替换函数中的关键字,类似我们的宏。对于非类型参数,可以是一个整型常量,或者是一个指向对象或者函数的指针或者引用等具有全局生命周期的类型,不能把普通局部变量或者动态绑定的等不确定值的变量作为非类型形参。下面我们还是写一段完整的程序来加深理解吧。#include <stdio.h> #include <iostream> using namespace std; /***以整型作为模板的非类型参数 ***/ template<class T,int MAX> void INT_fun(T data) { cout << data << " " << MAX << endl; } /***以指针作为模板的非类型参数 ***/ template<const char *C> void POINT_fun(intdata) { cout << C << " "<< data << endl; } /***以引用作为模板的非类型参数 ***/ template<char&T> void DES_fun() { cout << T << endl; } /***以函数指针作为模板的非类型参数 ***/ template<void(*f)()> void FUN_fun() { f(); } void test() { cout << "justa test" << endl; } char a[20]="C++,template"; char b = 'F'; int main() { INT_fun<int ,100>(10); POINT_fun<a>(10); DES_fun<b>(); FUN_fun<DES_fun<b>>(); FUN_fun<test>(); }
有关函数模板,我们还是要搞清楚其格式,其用法其实一般来说比较简单,关键是细节格式需要我们注意,初学阶段都是模仿,后面自然就熟能生巧了。
二、类模板
类模板跟函数模板的定义和使用类似,其也是为了减少代码中的重复部分,增加代码的可重用性,其参数可以是类型参数,也可以是非类型参数,但是与函数模版不同的是,编译器不能为类模板推断出参数的类型,因此我们必须显示的提供模板的实参。有关类模板的使用,我们依然需要注意其格式规范。下面我们就结合代码来介绍。#include <iostream> #include <stdio.h> using namespace std; template<class T> class Test { public: Test(T a, T b); T Max(); private: T a; T b; static T temp ; }; /********在类外实现成员函数*********/ template<typename T> Test<T>::Test(T a, T b) { Test::a = a; Test::b = b; } template<class T> T Test<T>::Max() { returna>b?a:b; } template<classT> int Test<T>::temp= 100; int main() { Test<int>t1(1,2); Test<float>t2(1.6,2.8); Test<float>t3('a','A'); cout << t1.Max() << endl; cout << t2.Max()<< endl; cout << (char)t3.Max() << endl; }在这段程序中,我们定义了一个模板类Test,有两个成员函数,两个数据成员和一个静态成员,成员函数和静态变量在类外进行实现,这里需要注意,在类外实现的时候,每一个实现前都要加上模板的声明,并且在写类名时也要加上模板,而在类里面时则不需要加了。最后在主函数中,我们实例化了三个模板类对象,在实例化类对象的时候,我们必须显示的指定类型参数,如此才能正确编译。
相关文章推荐
- C++中#include <climits>
- C++类构造函数初始化列表
- C语言的赋值语句是不是原子操作?
- 写给C语言初学者的话
- C++操作符的优先级
- C++模板元编程 - 2 模仿haskell的列表以及相关操作
- C++--------------------------------------------运算符重载
- C语言介绍
- 【c++学习笔记】指针
- C语言中如何用printf函数输出百分号?
- C++--------------------------------------获得整数数组第二大的数
- C++重载操作符总结
- c++ set multiset
- C语言反向链式栈的实现
- 使用C++11 开发一个半同步半异步线程池
- C语言正向链表栈的实现
- c++ iterator(迭代器)分类及其使用
- C++命名空间
- TQ2440 学习笔记—— 14、GPIO 接口【实验:用C语言实现】
- C语言正数和负数循环右移,左移,把某正数的第m位(从0开始)到n位取反