C++ Primer复习和学习笔记 第十六章 模板与泛型编程
2015-01-26 10:05
549 查看
#include "D:\C++WORK\main.h" template<typename T1,typename T2> T1 & print(T1 & s,T2 val) { s<<val; return s; } int main() { double dval=0.88; float fval=-12.3; string oristr="this is a test ",desstr; ostringstream oss(desstr); ofstream outFile("result.dat"); //写至cout print(cout,-3)<<endl; print(cout,dval)<<endl; print(cout,fval)<<endl; print(cout,oristr)<<endl; //写至文件 print(outFile,-3)<<endl; print(outFile,dval)<<endl; print(outFile,fval)<<endl; print(outFile,oristr)<<endl; outFile.close();//对文件写完之后,需要关闭文件 //写至stringstream print(oss,-3)<<endl; print(oss,dval)<<endl; print(oss,fval)<<endl; print(oss,oristr)<<endl; //将stringstream中的字符串输出到cout以验证 cout<<oss.str()<<endl; /*【】【】【】【】【】【】【】【】【】【】【】【】 关于stringstream::str()函数的用法【】【】【】【】【】【】【】【】【】【】【】【】 Get/set content 获取和设置内容 The first form (1) returns a string object with a copy of the current contents of the stream. The second form (2) sets s as the contents of the stream, discarding any previous contents. The object preserves its open mode: if this includes ios_base::ate, the writing position is moved to the end of the new sequence. Internally, the function calls the str member of its internal string buffer object. int main () { std::stringstream ss; ss.str ("Example string");//设置ss的数值 std::string s = ss.str();//获取ss的数值 std::cout << s << '\n'; return 0; } */ return 0; }
/*------------------------------------------------------------------------------- 编写一个函数模板,接受表示未知类型迭代器的一对值,找出在序列中出现得最频繁的值。 ---------------------------------------------------------------------------------*/ #include "iostream" #include "vector" #include "string" #include "list" #include "deque" #include "utility" #include "map" #include "set" #include "fstream" #include "sstream" #include "algorithm" #include "numeric" #include "iterator" #include "functional" #include "typeinfo.h" #include "memory" using namespace std; template < typename T >//输入参数T是迭代器类型。 typename T::value_type mostFre(T first, T last) //注意这里的typename T::value_type 这是在模板内部定义指定类型 /*-------------------------------------------------------------------------------------------------------------------- 这个程序中第一个关键的地方就是迭代器中有一个成员,就是value_type vector< int > vec;vec中的元素是{0,1,2,3,4}。vector< int >::iterator::value_type a = vec[4]; -----------------------------------------------------------------------------------------------------------------------*/ { allocator< typename T::value_type > alloc;//用于分配T::value_type类型内存的对象 alloc。 //分配内存用于保存输入序列的副本。 T::value_type * newFirst = alloc.allocate(last - first);//分配原始的构造内存以保存T::value_type类型的n=last-first个对象. T::value_type * newLast = newFirst + ( last - first ); //将输入序列复制到新分配的内存空间 uninitialized_copy(first, last, newFirst); //对副本序列进行排序,是的相同的值出现在相邻的位置。 sort(newFirst, newLast); size_t maxOccu = 0,occu = 0;//最频繁的出现次数,当前值出现次数 T::value_type * preIter = newFirst; T::value_type * maxOccuElemIt = newFirst;//指向当前值的前一个值,当前出现最频繁的值。 while ( newFirst != newLast ) { if ( *newFirst != *preIter ) { if (occu > maxOccu) { maxOccu = occu; maxOccuElemIt = preIter; } occu = 0; } ++occu; preIter = newFirst; ++newFirst; } if ( occu > maxOccu) { maxOccu = occu; maxOccuElemIt = preIter; } return *maxOccuElemIt; } int main() { int a[30] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 5 }; vector< int > vec(a,a+30); vector< int >::iterator iter_begin = vec.begin(); vector< int >::iterator iter_end = vec.end(); int Ncount = mostFre(iter_begin, iter_end); cout <<"元素出现次数最多的元素是:"<<Ncount << endl; string str = "hhhhhello!"; string::iterator it_begin = str.begin(); string::iterator it_end = str.end(); cout << "元素出现次数最多的元素是:" << mostFre(it_begin, it_end)<< endl; /*----------------------------------------------------------------------------------------------------------------------------*/ allocator< int > alloc; if ( typeid( vector< int >::iterator ) != typeid( alloc.allocate(iter_end - iter_begin) ) ) { cout << " \n vector< int >::iterator 和 alloc.allocate(iter_end - iter_begin) 不是相同类型 \n " << endl; } if ( typeid(vector< int >::iterator::value_type *) == typeid(alloc.allocate(iter_end - iter_begin)) ) { cout << " \n vector< int >::iterator::value_type 和 alloc.allocate(iter_end - iter_begin) 是相同类型 \n " << endl; } /* 注意这里也就是上面的mostFre()函数中,答案书上错误的地方。答案书上面写的是 T newFirst = alloc.allocate( last - first ); 但是你真正编译程序的时候会出现大量的错误,其中最关键的一条就是: 错误1 error C2440: “初始化”: 无法从“int *”转换为“std::_Vector_iterator<std::_Vector_val<std::_Simple_types<int>>>” 本以为书上不会出现任何错误,但是问题出现了。 */ /*----------------------------------------------------------------------------------------------------------------------------*/ return 0; }
/*---------------------------------------------------------------------------------------------------------------- 编写一个函数模板,这个函数模板,有一个类型模板形参和一个非类型模板形参。用来接收一个数组,并给这个数组赋值 -----------------------------------------------------------------------------------------------------------------*/ #include "iostream" #include "vector" #include "string" #include "list" #include "deque" #include "utility" #include "map" #include "set" #include "fstream" #include "sstream" #include "algorithm" #include "numeric" #include "iterator" #include "functional" #include "typeinfo.h" #include "memory" using namespace std; template < typename T , size_t N > void array_init( T (&parm) ) { for (size_t i = 0; i != N; ++i) { parm[i] = i; cout << parm[i] << endl; } } int main() { int a[10]; array_init(a); double b[20]; array_init(b); }
在《C++ Primer 第四版》的第七章中,讲到了通过引用传递数组,和其他类型一样,数组形参可声明为数组的引用。如果形参是数组的引用,编译器不会将数组实参转化为指针,而是传递数组的引用本身。在这种情况下,数组大小成为形参与实参类型的一部分,编译器检查数组实参的大小与形参的大小是否匹配。
#include <iostream> using namespace std; void output(int (&a)[5])//数组的引用作为函数的形参。 { for(int i = 0; i < 5; i++) cout<<a[i]<<endl; } int main() { int a[5]={0}; output(a); getchar(); return 0; }
#include <iostream> using namespace std; int main() { int a[5]={0}; int (&b)[5] = a;//直接声明一个数组的引用。 for(int i = 0; i < 5; i++) cout<<b[i]<<endl; cout<<sizeof(b); getchar(); return 0; }
你可以创建对数组的引用,但你不能创建一个元素都是引用的数组。
/*------------------------------------------------------------------------------- 编写一个函数模板,接受表示未知类型迭代器的一对值,找出在序列中出现得最频繁的值。 ---------------------------------------------------------------------------------*/ #include "iostream" #include "vector" #include "string" #include "list" #include "deque" #include "utility" #include "map" #include "set" #include "fstream" #include "sstream" #include "algorithm" #include "numeric" #include "iterator" #include "functional" #include "typeinfo.h" #include "memory" using namespace std; template <typename U> int compare(U u1, U u2) { cout << "使用模板" << endl; return 0; } int compare(int a, int b) { cout << "使用compare( int a,int b)函数" << endl; return 0; } int main() { int a = 10, b = 20; short s1 = 30, s2 = 40; compare(s1, s2);//使用模板。并没有把short类型提升为int类型然后调用compare(int,int) compare(a, b);//使用compare(int a, int b)函数,并没有调用函数模板。而是直接使用已经有的函数。 return 0; }
/*------------------------------------------------------------------------------- 确定模板形参调用哪个函数。 ---------------------------------------------------------------------------------*/ #include "iostream" #include "vector" #include "string" #include "list" #include "deque" #include "utility" #include "map" #include "set" #include "fstream" #include "sstream" #include "algorithm" #include "numeric" #include "iterator" #include "functional" #include "typeinfo.h" #include "memory" using namespace std; template < typename T1> int compare(const T1&, const T1&) { if (typeid(T1)==typeid(int)) { cout << "copare函数模板的实参是:int 类型 " << endl; } else if (typeid(T1)==typeid(string)) { cout << "compare函数模板的实参是:string类型" << endl; } return 0; } void func(int(*p) (const string &, const string &)) { string str1 = "hello", str2 = "world"; p(str1, str2); cout << "void func(int(*) (const string &, const string &))" << endl; } void func(int(*p) (const int & , const int & )) { int a = 10; int b = 20; p(a, b); cout << "void func(int(*) (const int &, const int &))" << endl; } int main() { func(compare); /*错误 1 error C2668: “func”: 对重载函数的调用不明确。 因为有两个可以用来调用 一个是int 一个是string所以会产生冲突。 template < typename T1> int compare(const T1&, const T1&) 我们看这个模板,有一个模板形参 T1 而且compare()函数中的形参也只有一个T1 所以,我们就可以通过指定 T1 来指定调用哪个函数。 */ func( compare<int> ); func(compare<string>); return 0; }
/*本程序是为了演示模板编译模型中的【包含编译模型】 这个文件是median.h头文件,这个头文件是模板的声明。*/ #ifndef _MEDIAN_H_ #define _MEDIAN_H_ //#include "vector" //#include "algorithm" //这里有没有都没有问题。 using std::vector; /* 如果这里不使用 using std::vector那么就会出错。 语法错误 : 缺少“,”(在“<”的前面) */ template < typename T > bool median( const vector < T > & , T & ); #include "median.cpp" #endif
/*这个cpp文件是median.cpp文件。其中的内容是模板的实现。注意在vs2013中这个实现文件千万不要添加到项目中,否则就会出现编译的问题。要把这个文件从项目中移出*/ template < typename T> bool median( const vector<T> & t , T & tVal ) { vector<T> temp(t);//临时的vector if (0 == temp.size() % 2) { return false; } vector<T>::iterator iter_begin = temp.begin(); vector<T>::iterator iter_end = temp.begin(); sort(iter_begin, iter_end); vector<T>::size_type mid = temp.size() / 2; if (temp[mid] > temp[mid - 1] && temp[mid] < temp[mid + 1]) { tVal = temp[mid]; return true; } else { return false; } }
/*------------------------------------------------------------------------------- 模板编译模型中的包含编译模型。主程序,用来调用模板。 ---------------------------------------------------------------------------------*/ #include "iostream" #include "vector" #include "string" #include "list" #include "deque" #include "utility" #include "map" #include "set" #include "fstream" #include "sstream" #include "algorithm" #include "numeric" #include "iterator" #include "functional" #include "typeinfo.h" #include "memory" #include "median.h" using namespace std; int main() { int a[4] = { 1, 2, 3, 4 }; int a1[7] = { 1, 2, 3, 4, 5, 6, 7 }; int a2[9] = { 1, 2, 3, 4, 5, 6, 7, 8, 9 }; vector<int> vec(a, a + 4); int m=0; median(vec, m); cout << m << endl; vector<int> vec1(a1, a1 + 7); median(vec1, m); cout << m << endl; vector<int> vec2(a2, a2 + 9); median(vec2, m); cout << m << endl; }
#include "iostream"//模板的特化操作的例子。模板特化的时候调用函数的次序。 #include "vector" #include "string" #include "list" #include "deque" #include "utility" #include "map" #include "set" #include "fstream" #include "sstream" #include "algorithm" #include "numeric" #include "iterator" #include "functional" #include "typeinfo.h" #include "memory" using namespace std; template < typename T> int compare(const T & t1, const T & t2) { cout << "调用的是:\n template < typename T> int compare(const T & t1, const T & t2)" << endl; return 0; } //特化的模板函数 template <> int compare<const char *>(const char * const & t1, const char * const & t2) { cout << "调用的是特化的模板:\n int compare<const char *>(const char * const T & t1, const char * const T & t2)" << endl; return 0; } int compare(const char * & t1, const char * & t2) {/*注意有特化的const char *参数的函数 和 专门的const char * 函数。那么首先调用专门的函数。 如果没有专门的函数,那么才会调用特化的模板函数。*/ cout << "调用:\n int compare(const char * & t1, const char * & t2)" << endl; return 0; } int main() { const char * c1 = "hello"; const char * c2 = "world"; compare(c1, c2);//注意这个函数的调用。 int a = 10, b = 20; compare(a, b); double c = 10.0, d = 20.0; compare(c, d); return 0; }
相关文章推荐
- 【C++ Primer】【学习笔记】【第十六章】模板与泛型编程之一:模板定义
- C++ Primer 学习笔记_80_模板与泛型编程 -类模板成员
- C++ Primer 学习笔记_75_模板与泛型编程 -模板定义
- C++ Primer 学习笔记_86_模板与泛型编程 -满载与函数模板
- C++ Primer 学习笔记_81_模板与泛型编程 -类模板成员[续一]
- C++ Primer 学习笔记_84_模板与泛型编程 --模板特化
- C++ Primer 学习笔记_76_模板和泛型编程 --模板定义[继续]
- C++ Primer 学习笔记_78_模板与泛型编程 -实例化[续]
- C++ Primer 学习笔记_83_模板与泛型编程 -一个泛型句柄类
- C++ Primer 学习笔记_79_模板与泛型编程 --模板编译模型
- C++ Primer 学习笔记_79_模板与泛型编程 -模板编译模型
- C++ Primer 学习笔记_82_模板与泛型编程 -类模板成员[续二]
- C++ Primer 学习笔记_85_模板与泛型编程 -模板特化[续]
- C++ Primer 学习笔记_76_模板与泛型编程 --模板定义[续]
- C++ Primer 学习笔记_76_模板与泛型编程 -模板定义[续]
- C++ Primer 学习笔记_85_模板与泛型编程 --模板特化[续]
- C++ Primer 学习笔记_83_模板与泛型编程 --一个泛型句柄类
- C++ Primer 学习笔记_84_模板与泛型编程 -模板特化
- C++ Primer 学习笔记_77_模板与泛型编程 -实例化
- C++ Primer 学习笔记十六 —— 模板与泛型编程