SlideShare a Scribd company logo
1 of 33
C++ トレーニング C++ template & Generic programing  --Getting started Poseidonproject
基本Thread ,[object Object]
为什么引入泛型
C++函数模板定义1 3 4 2 6 5 ,[object Object]
还为涉及的模板领域
C++类模板定义2
为什么要引入泛型 泛型是什么? 泛型编程又是什么呢? 3
为什么要引入泛型 泛型 就是C++模板的一种表现,也即类型参数化。 泛型编程(Generic Programming)  是建立在C++的Template机制基础上的一种完全不同于面向对象的程序设计思维模式。 典型作品:STL 4
为什么要引入泛型 为什么需要泛型编程? 5
为什么要引入泛型 C++ template的最初发展动机很直接:让我们得以建立类型安全(type-safe)的通用容器。 如:vecotr,list,map等。 当愈多人用上template时,他们发现template有能力完成愈多可能的变化。容器当然很好。 但是泛型编程(Generic Programming)--写出的代码和其所处理的对象类型彼此独立。 于是STL的各种算法就应运而生。 如:for_each, find, merge等。 6
为什么要引入泛型 简单的一个开发场景说明 主角:小逗童鞋 1 简单的一个开发任务 任务内容:编写compare函数,分别比较int、string、double三种类型值的大小。要求比较的两个值通过参数传入compare函数中,如果第一个值大于第二个值,就然会1,如果小于就返回-1,否则返回0。 2 日本项目中抽取的一个实例 模板函数实例 3
简单的一个案例分析 小逗提交了如下代码: int compare(const int& v1, cosnt int& v2) {     if (v1 > v2) return 1;     else if (v2 > v1) return -1;     return 0; } int compare(const string& v1, const string& v2) {     if (v1 > v2) return 1;     else if (v2 > v1) return -1;     return 0; } int compare(const double& v1, const double& v2) {     if (v1 > v2) return 1;     else if (v2 > v1) return -1;     return 0; } 8
简单的一个案例分析 小逗的主管帮小逗一起评审了这个几个函数的问题: ,[object Object]
 那有什么办法解决这个问题吗?9
简单的一个案例分析 Google之后的结论是,可以通过如下两种解决办法来处理: ,[object Object],Java以及C#中的超类,所有的类都继承与它。 通过存储基类的引用,从而通过超类的引用访问。 ,[object Object],这也正是泛型的简单定义。通过C++的模板template方式来实现。 小逗在学习了模板之后,用模板的方法解决了主管提出的问题,重构了之前的代码: template<typename T> int compare(const T& v1, const T& v2) {     if (v1 > v2) return 1;     else if (v2 > v1) return -1;     return 0;   } 小逗通过自己的努力,逐渐掌握了如何来编写一个模板函数方法。 10
简单的一个案例分析 日本项目的一个实例应用: 简单需求:处理市场发送过来的广播消息,消息数量大于有7,8种。 每种广播消息的格式的定义如下: typedef struct broadcast_message_type {    broadcast_type_t broadcast_type;    uint16_t items_n;    char filler_2_s [2];    broadcast_message_type_item_t item [9]; 每个item对应一只股票。 } broadcast_message_type _t; 现在需求是,需要把每个广播消息中对应items下面的每一只股票发送给其他线程处理。 11
简单的一个案例分析 发送消息的模板函数: template <typename msgT, typename memberT> void BOMXFFHBroadcastController::sendMessage(     char* broadcast,      ENDataEventType event_type) {     msgT* message_serise = (msgT*)broadcast;     char* data_ptr = broadcast;     uint16_t items = message_serise->items_n;     series_t series_key;     data_ptr += offsetof(msgT, item);     for (uint16_t index = 0; index < items; index++) {         series_key = message_serise->item[index].series;               sendDirectMessage(data_ptr, sizeof(memberT), event_type, series_key);         data_ptr += sizeof(memberT);     } } 12
如何引入泛型 1、C++引入单根继承 2、参数化类型 实现通用容器的方案就是使用“参数化类型”。 一个容器需要能够存放任何类型的对象,那干脆就把这个对象的类型“抽”出来,参数化它:   template<class T> class vector {     T* v;     int sz;     public:         vector(int);         T& operator[](int);         T& elem(int i) { return v[i]; }         // ... }; 13
如何引入泛型 宏不能解决这个问题吗? 那么与模板相比,宏有什么缺点呢? 14
如何引入泛型 跟模板相比,宏的最大的缺点就是它并不工作在C++的语法解析层面,宏是由预处理器来处理的,而在预处理器的眼里没有C++,只有一堆文本,只做简单的替换。因此C++的类型检查根本不起作用。 比如上面的定义如果用宏来实现,那么就算你传进去的T不是一个类型,预处理器也不会报错;只有等到文本替换完了,到C++编译器工作的时候才会发现一堆莫名其妙的类型错误,但那个时候错误就已经到处都是了。往往最后会抛出一堆吓人的编译错误。 更何况宏的调试有困难。   15
为什么要引入泛型 我们再来看一看通用算法,这是泛型的另一个动机。比如我们熟悉的C的qsort:   void qsort(void *base, size_t nmemb, size_t size,int (*compar)(const void *, const void *));   16
为什么要引入泛型 这个算法有如下几个问题:   1.  类型安全性:使用者必须自行保证base指向的数组的元素类型和compar的两个参数的类型是一致的;使用者必须自行保证size必须是数组元素类型的大小。 2.  通用性:qsort对参数数组的二进制接口有严格要求——它必须是一个内存连续的数组。如果你实现了一个巧妙的、分段连续的自定义数组,就没法使用qsort了。 3.  接口直观性:如果你有一个数组char* arr = new arr[10];那么该数组的元素类型其实就已经“透露”了它自己的大小。然而qsort把数组的元素类型给“void”掉了(void *base),于是丢失掉了这一信息,而只能让调用方手动提供一个size。为什么要把数组类型声明为void*?因为除此之外别无它法,声明为任意一个类型的指针都不妥(compar的参数类型也是如此)。qsort为了通用性,把类型信息丢掉了,进而导致了必须用额外的参数来提供类型大小信息。在这个特定的算法里问题还不明显,毕竟只多一个size参数而已,但一旦涉及的类型信息多了起来,其接口的可伸缩性(scalability)问题和直观性问题就会逐渐显现。 4.  效率:compar是通过函数指针调用的,这带来了一定的开销。但跟上面的其它问题比起来这个问题还不是最严重的。 17
函数和类模板 那该如何编写一个C++模板呢? ,[object Object]
 类模板 18
函数模板(Function template)大解剖 定义C++ 模板的关键字 模板定义都以它开头。 template <typename T, size_t N> T sumArray(T (&arr)[N]) {     T sum=0; for (int i = 0; i < N; ++i) {         sum += arr[i];     }     return sum; } 模板形参表 表示类型的类型形参(T) 表示常量表达式的非类型形参(N)。 模板函数体 在模板函数内部,可以使用类型形参 T 引用一个类型,T 表示哪种实际类型由编译器根据所用的函数而确定。 sumArray<int, 10>(array)  <<--称之为模板的实例化(显示的模板实参),在编译阶段完成。 inline函数模板: template <typename T> inline T min(const T&, const T&);  ○ inline template <typename T> T min(const T&, const T&); × 注意inline关键字的位置 非类型形参为啥是常量表达式? 19
函数模板(Function template)大解剖 C++ Function Template Overloading template <class T> inline const T& min(const T& a, const T& b) {       return b < a ? b : a; } 例如: r3 = min(r1, r2); 编译器做参数推导。 ■任何类型对象都可以 运用min(), 需要支持 operator<。 template <class T, class C> inline const T& min(const T& a, const T& b, C comp) {         return comp(b, a) ? b : a; } 例如: r3 = min(r1, r2, compare); 编译器做参数推导。 ■需要根据类型自定义 比较函数,传入函数指针。 传入函数对象可以吗? 20
类模板(class template)大解剖 定义C++ 类模板的关键字 类模板定义都以它开头。 template < typename T, size_t N = 32> class BFixedArray { public:      explicit BFixedArray(size_t dim = N)         : _cItems(dim), _buffer(_internal)      {         if(dim > THRESHOLD) {             _buffer = new T[dim];         }      }     ~BFixedArray() {         if (!isOnStack()) {             delete[] _buffer;         }     }     size_t size() const {         return _cItems;     } 模板形参表 表示类型的类型形参(T) 表示常量表达式的非类型形参(N)。 类模板定义体 在类模板内部,可以使用类型形参 T 引用一个类型,T 表示哪种实际类型由编译器根据所用的函数而确定。 编译器将使用用户提供的实际类型来实例化这个类模板。 BFixedArray<char, 128> sendbuffer(length); BFixedArray<int, 128> fixedBuffer(length); 类型形参由关键字class或typename后街说明符构成。在模板形参表中,这两个关键字具有相同的含义,都指出后面所接的名字表示一个类型。 当然在模板的使用上,也是有不同之处(在模板定义内部指定类型)  21
类模板(class template)大解剖 定义C++ 类模板的关键字 类模板定义都以它开头。 template <class _Tp, class _Alloc> void slist<_Tp,_Alloc>::remove(const _Tp& __val) {   _Node_base* __cur = &this->_M_head;   while (__cur && __cur->_M_next) {     if (((_Node*) __cur->_M_next)->_M_data == __val)       this->_M_erase_after(__cur);     else       __cur = __cur->_M_next;   } } 类模板形参表 类模板成员函数作用域 类模板成员函数返回值 类模板成员函数定义 类模板成员函数 or 成员模板? 22
类模板成员函数(class template member)大解剖 定义C++ 类模板的关键字 类模板定义都以它开头。 template <class _Tp, class _Alloc> void slist<_Tp,_Alloc>::remove(const _Tp& __val) {   _Node_base* __cur = &this->_M_head;   while (__cur && __cur->_M_next) {     if (((_Node*) __cur->_M_next)->_M_data == __val)       this->_M_erase_after(__cur);     else       __cur = __cur->_M_next;   } } 类模板形参表 类模板成员函数作用域 类模板成员函数返回值 类模板成员函数定义 类模板成员函数 or 成员模板? 23
类成员模板(class member template )大解剖 定义C++ 类模板的关键字 类模板定义都以它开头。 template <class _Tp, class _Alloc> template <class _InputIter> void vector<_Tp,_Alloc>::_M_assign_aux(_InputIter __first, _InputIter __last,                                         input_iterator_tag) {   iterator __cur = begin();   for ( ; __first != __last && __cur != end(); ++__cur, ++__first)     *__cur = *__first;   if (__first == __last)     erase(__cur, end());   else     insert(end(), __first, __last); } 类模板形参表 类成员模板的模板形参表 类成员模板的函数声明部分 ,[object Object]
 类模板作用域
 函数定义声明类成员模板的函数定义 ,[object Object]
 删除该容器中原有的元素。

More Related Content

Similar to C++模板与泛型编程

ADO.NET Entity Framework 4
ADO.NET Entity Framework 4ADO.NET Entity Framework 4
ADO.NET Entity Framework 4Raffaele Fanizzi
 
Lecture7
Lecture7Lecture7
Lecture7orgil
 
100526 windows7 mfc_최성기_배포용
100526 windows7 mfc_최성기_배포용100526 windows7 mfc_최성기_배포용
100526 windows7 mfc_최성기_배포용sung ki choi
 
Javaバイトコード入門
Javaバイトコード入門Javaバイトコード入門
Javaバイトコード入門Kota Mizushima
 
Lecture1
Lecture1Lecture1
Lecture1orgil
 
03 3-create-db-application-ado-dot-net Create Database Application with using...
03 3-create-db-application-ado-dot-net Create Database Application with using...03 3-create-db-application-ado-dot-net Create Database Application with using...
03 3-create-db-application-ado-dot-net Create Database Application with using...Warawut
 
Lecture6
Lecture6Lecture6
Lecture6orgil
 
Qt编程介绍
Qt编程介绍Qt编程介绍
Qt编程介绍easychen
 
C# für Fortgeschrittene
C# für FortgeschritteneC# für Fortgeschrittene
C# für Fortgeschrittenemspgermany
 
04 practical symfony 4дөх
04 practical symfony 4дөх04 practical symfony 4дөх
04 practical symfony 4дөхtuvshinmgl
 
Java Forum Stuttgart 2010: Scala 2.8.0 - Was gibt's Neues?
Java Forum Stuttgart 2010: Scala 2.8.0 - Was gibt's Neues?Java Forum Stuttgart 2010: Scala 2.8.0 - Was gibt's Neues?
Java Forum Stuttgart 2010: Scala 2.8.0 - Was gibt's Neues?Oliver Braun
 

Similar to C++模板与泛型编程 (13)

ADO.NET Entity Framework 4
ADO.NET Entity Framework 4ADO.NET Entity Framework 4
ADO.NET Entity Framework 4
 
Clase5_Python-CTIC
Clase5_Python-CTICClase5_Python-CTIC
Clase5_Python-CTIC
 
Lecture7
Lecture7Lecture7
Lecture7
 
100526 windows7 mfc_최성기_배포용
100526 windows7 mfc_최성기_배포용100526 windows7 mfc_최성기_배포용
100526 windows7 mfc_최성기_배포용
 
Javaバイトコード入門
Javaバイトコード入門Javaバイトコード入門
Javaバイトコード入門
 
Türsteher für Bohnen
Türsteher für BohnenTürsteher für Bohnen
Türsteher für Bohnen
 
Lecture1
Lecture1Lecture1
Lecture1
 
03 3-create-db-application-ado-dot-net Create Database Application with using...
03 3-create-db-application-ado-dot-net Create Database Application with using...03 3-create-db-application-ado-dot-net Create Database Application with using...
03 3-create-db-application-ado-dot-net Create Database Application with using...
 
Lecture6
Lecture6Lecture6
Lecture6
 
Qt编程介绍
Qt编程介绍Qt编程介绍
Qt编程介绍
 
C# für Fortgeschrittene
C# für FortgeschritteneC# für Fortgeschrittene
C# für Fortgeschrittene
 
04 practical symfony 4дөх
04 practical symfony 4дөх04 practical symfony 4дөх
04 practical symfony 4дөх
 
Java Forum Stuttgart 2010: Scala 2.8.0 - Was gibt's Neues?
Java Forum Stuttgart 2010: Scala 2.8.0 - Was gibt's Neues?Java Forum Stuttgart 2010: Scala 2.8.0 - Was gibt's Neues?
Java Forum Stuttgart 2010: Scala 2.8.0 - Was gibt's Neues?
 

C++模板与泛型编程