模板template课后笔记

来源:互联网 发布:有线网络转无线wifi 编辑:程序博客网 时间:2024/06/05 07:57

Template C++,这是C++的泛型编程(generic programming)部分,貌似是大多数普通程序员经验最少的部分。

为什么要用templates?

假设我需要两个list,list_X和list_Y,现要求两者分别存储不同的数据类型,其他都是一样。

在这里我们会有什么办法?

1.X和Y有共同的基类(base class)

×但是这样并不是很理想,比如X里面存放的是苹果,Y里面放的是笔,两者的共同基类可能就是东西,这两者很难统一起来。

2.克隆代码

×这种方式,对后续的代码管理和维护会造成很大的不良影响。

3.没有类型的list

×设想list放void *类型,可以将X和Y的指针给它,但是这样是不安全的,因为不知道取出来的是X还是Y。

4.使用template

使得我们可以用另外一种方式去重用代码(reuse source code),类型成为template的参数

所以才选择使用template

对于template,有function template 和 class template,

这里需要提4个名词:

1.函数模板(是一种模板用来做出函数,叫做function template),

2.模板函数(template function),

3.类模板(是一种模板用来做出类),

4.模板类(template class)。


对于Template functions,比如sort function,做排序的函数,这是一种常见的template,因为你需要sort不同类型

对于Template classess,比如containers 容器,如stack ,list,queue...


Example:swap function template

#include <iostream>template <class T>//template <class >都是不可更换,而T不是,T可以更换成其他的,但是习惯性采用T//template 关键词是表明:现在有一个template,这个template里面有一个参数T,在我这一行往下,下一个东西就是template,如果下一个是函数,那这个函数就是template,如果是类,那这个类就是template。 //下面这个swap就变为了函数模板,在这个函数里面可以使用T,来代表一个类型void swap(T &X,T &Y){T temp = X;X = Y;Y = temp;}int main(){int i = 8;int j = 9;std::cout<<"i="<<i<<"\n";std::cout<<"j="<<j<<"\n";swap(i, j);std::cout<<"after swap:\n";std::cout<<"i="<<i<<"\n";std::cout<<"j="<<j<<"\n";float k = 4.5;float m = 3.7;//1.0是double,没有加f后缀的带小数点的数是double而不是float。这个知识点容易忘掉std::cout<<"k="<<k<<"\n";std::cout<<"m="<<m<<"\n";swap(k,m);std::cout<<"after swap:\n";std::cout<<"k="<<k<<"\n";std::cout<<"m="<<m<<"\n";return 0;}


类 实例化生成 实例(对象)
函数模板 实例化生成 模板函数
A template function is an instantiation of a function template.

模板是一种声明,而不是定义,编译器只是记下模板,然后知道了具体的类型才定义。

如果函数的参数表没有类型,类型出现在函数体的话就要显式表达:

template<class T>void foo(void){/*..*/}foo<int>();foo<float>();




Example: Vector

#include <iostream>template <class T>//类模板里面的每一个函数都是函数模板class Vector{public:Vector(int);~Vector();Vector(const Vector&);Vector& operator= (const Vector&);//类模板的成员函数就比较麻烦了:每个成员函数都是函数模板,都要加上 template <class T>private:T* m_elements;int m_size;};int main(){Vector<int> v1(100);return 0 ;}


Template can use multiple types

template<class Key, class Value>class HashTable{const Value& lookup(const Key&) const;void install(const Key&, const Value&);...};

Template nest :they are just new type!

Vector< Vector<double *> >//后面两个大于号之间应该放空格区分!这行表明一个Vector,这个Vector里面的每一个单元都是Vector,那个Vector里面的每一个单元都是double的指针。


Type arguments can be complicated

Vector< int(*)(Vector<double>&,int) >//Vector里面的成员是一个函数指针,这个函数指针的函数返回的是int,它的参数表是两项,第一项是一个类型为double的Vector引用,第二项是int

表达式参数 Expression parameters

template <class T, int bounds = 100>class FixedVector{public:FixedVector();//...private:T elements[bounds];//fixed size array}FixedVector<int, 50> v1;FixedVector<int> v2; //default

对于Template的关键字typename和class:
The only difference between both prototypes is the use of either the keyword class or the keyword typename. Its use is indistinct, since both expressions have exactly the same meaning and behave exactly the same way.


from http://www.cplusplus.com/doc/tutorial/templates.html


stack模板:

#ifndef STACK_H#define STACK_Htemplate<typename T>class Stack{public:Stack(int =10);~Stack(){delete[] stackPtr;}enum error_code{sucess, //正常执行underflow, //没有元素而删除元素时overflow //没有空间而插入元素时};bool push(const T&);//bool pop(T&);bool isEmpty() const{return top == -1;}bool isFull() const{return top == size - 1;}private:int size;int top;T *stackPtr;}; //end class template Stacktemplate <typename T>Stack<T>::Stack(int s) :size(s > 0 ? s : 10), top(-1), stackPtr(new T[size]){}template <typename T>bool Stack<T>::push(const T &pushValue){if (!isFull()){stackPtr[++top] = pushValue;return true;}return false;}template <typename T>bool Stack<T>::pop(T &popValue){if (!isEmpty()){popValue = stackPtr[top--];return true;}return false;}#endif // STACK_H

cpp:

#include "Stack.h"#include <iostream>using namespace std;int main(){Stack <double> doubleStack;double doubleValue = 1.1;cout << "push\n";while (doubleStack.push(doubleValue)){cout << doubleValue <<' ';doubleValue += 1.1;}cout << "\n Stack is full, can not push " << doubleValue << "\npopping elements from doubleStack\n";while (doubleStack.pop(doubleValue)){cout << doubleValue << ' ';}cout << "\n Stack is empty\n";}




0 0
原创粉丝点击