C++03_template

来源:互联网 发布:招商加盟网络推广计划 编辑:程序博客网 时间:2024/06/05 09:03

关于嵌套的类的template举例:


//queuetp.h -- queue template with a nested typename

template<typenameItem>

classQueueTP

{

private:

enum{Q_SIZE= 10};

//Node is a nested typename definition

classNode

{

public:

Itemitem;

Node*next;

Node(constItem& i):item(i),next(0){ }

};

Node*front; // pointer to front of Queue

Node*rear; // pointer to rear of Queue

intitems;// current number of items in Queue

constintqsize;// maximum number of items in Queue

QueueTP(constQueueTP &q) : qsize(0){}

QueueTP&operator=(constQueueTP &q) { return*this;}

public:

QueueTP(intqs = Q_SIZE);

~QueueTP();

boolisempty()const

{

returnitems == 0;

}

boolisfull()const

{

returnitems ==qsize;

}

intqueuecount()const

{

returnitems;

}

boolenqueue(constItem&item);// add item to end

booldequeue(Item&item);// remove item fromfront

};


//QueueTP methods

template<typenameItem>

QueueTP<Item>::QueueTP(intqs) : qsize(qs)

{

front=rear = 0;

items= 0;

}


template<typenameItem>

QueueTP<Item>::~QueueTP()

{

Node* temp;

while(front !=0) // while queue is not yet empty

{

temp =front;// save address of front item

front=front->next;//reset pointer to next item

deletetemp;// delete former front

}

}


//Add item to queue

template<typenameItem>

boolQueueTP<Item>::enqueue(constItem& item)

{

if(isfull())

returnfalse;

Node* add =newNode(item);// create node

if(add == 0)

returnfalse;// quit if none available

items++;

if(front ==0) // if queue is empty,

front= add;// place item at front

else

rear->next= add; // else place at rear

rear= add;// have rear point tonew node

returntrue;

}


//Place front item into item variable and remove from queue

template<typenameItem>

boolQueueTP<Item>::dequeue(Item& item)

{

if(front ==0)

returnfalse;

item =front->item;// set item to first item in queue

items--;

Node* temp =front; // save location of first item

front=front->next;// reset front to next item

deletetemp;// delete former firstitem

if(items ==0)

rear= 0;

returntrue;

}


****************************************************************************

定义和使用Pairtemplate


两种数据类型可以分别使用两种类类型


#include<iostream>

usingnamespacestd;


template<classT1,classT2>

classPair

{

private:

T1a;

T2b;

public:

T1&first(constT1 &f);

T2&second(constT2 &s);

T1first()const{returna; }

T2second()const{returnb; }

Pair(constT1 &f, constT2 &s) :a(f),b(s) { }

};


template<classT1,classT2>

T1&Pair<T1,T2>::first(constT1 &f)

{

a= f;

returna;

}

template<classT1,classT2>

T2&Pair<T1,T2>::second(constT2 &s)

{

b= s;

returnb;

}


intmain()

{

Pair<char*,int>ratings[4] =

{

Pair<char*,int>("ThePurple Duke", 5),

Pair<char*,int>("Jake'sFrisco Cafe", 4),

Pair<char*,int>("MontSouffle", 5),

Pair<char*,int>("Gertie'sEats", 3)

};


intjoints =sizeof(ratings)/sizeof(Pair<char*,int>);

cout <<"Rating:\t Eatery\n";

for(inti = 0; i < joints; i++)

cout <<ratings[i].second() <<":\t "

<<ratings[i].first() <<"\n";


ratings[3].second(6);

cout <<"Oops! Revised rating:\n";

cout <<ratings[3].second() <<":\t "

<<ratings[3].first() <<"\n";


return0;

}


************************************************************************

一个关于array类:


#ifndefARRAYTP_H_

#defineARRAYTP_H_


#include<iostream>

usingnamespacestd;

#include<cstdlib>


template<classT,intn>

classArrayTP

{

private:

Tar[n];

public:

ArrayTP(){};

explicitArrayTP(constT &v); //显性的复制构造函数!

//一般来说,假如程序员没有自行编写复制构造函数,

//那么编译器会自动地替每一个类型创建一个复制构造函数

//implicitcopy constructor,隐性的复制构造函数);

//相反地,程序员有自行编写复制构造函数(explicitcopy constructor

//显性的复制构造函数),那么编译器就不会创建它。

virtualT &operator[](inti);//为什么两次用相同的方式对【】重载????

//其中对[]两次重载,使用的时候[]=左面使用无const的重载,[]=右面使用有const的重载!!!!!

virtualconstT &operator[](inti)const;

};


template<classT,intn>

ArrayTP<T,n>::ArrayTP(constT &v)

{

for(inti = 0; i < n;i++)

ar[i]= v;

}


template<classT,intn>

T&ArrayTP<T,n>::operator[](inti)

{

if(i < 0 || i >=n)

{

cerr <<"Error in array limits: "<< i

<<" is out of range\n";

exit(1);

}

returnar[i];

}


template<classT,intn>

constT &ArrayTP<T,n>::operator[](inti)const

{

if(i < 0 || i >=n)

{

cerr <<"Error in array limits: "<< i

<<" is out of range\n";

exit(1);

}

returnar[i];

}


#endif



利用array类达到一下的输出结果


1 2 3 4 5 : sum = 15, average = 1.5

2 4 6 8 10 : sum = 30, average = 3

3 6 9 12 15 : sum = 45, average = 4.5

4 8 12 16 20 : sum = 60, average = 6

510 15 20 25 : sum = 75, average = 7.5

612 18 24 30 : sum = 90, average = 9

714 21 28 35 : sum = 105, average = 10.5

816 24 32 40 : sum = 120, average = 12

918 27 36 45 : sum = 135, average = 13.5

1020 30 40 50 : sum = 150, average = 15


主程序:


//twod.cpp -- making a 2-d array

#include<iostream>

usingnamespacestd;

#include"arraytp.h"

intmain(void)

{

ArrayTP<int,10> sums;

ArrayTP<double,10> aves;

ArrayTP<ArrayTP<int,5>,10> twodee;



inti, j;


for(i = 0; i < 10; i++)

{

sums[i] = 0;

for(j = 0; j < 5; j++) //每一行中的循环

{

twodee[i][j]= (i + 1) * (j + 1);

sums[i]+= twodee[i][j];

}

aves[i] =(double)sums[i] / 10;

}

for(i = 0; i < 10; i++) //循环输出1-10

{

for(j = 0; j < 5; j++) //一行之内循环5次,每次自加加行首的数!

{

cout.width(2);

cout <<twodee[i][j] <<' ';

}

cout <<": sum = ";

cout.width(3);

cout <<sums[i] <<", average = "<< aves[i] << endl;

}


cout <<"Done.\n";


return0;

}


******************************************************************************


定义一个栈类,在C++02中已经出现过了,只不过这次是template的形式,在主程序中将string(详细实现见C++02)类的object,进栈或是出栈!主程序中简单的用whileswitch对用户输入的命令,也就是string字符进行判断!


判断字符时涉及到一些函数:

toupper,tolower

convert letter to upper or lower case

isalpha()

checksfor an alphabetic character; in the standard "C" locale,it

is equivalent to (isupper(c) || islower(c)). In some locales,

theremay be additional characters for which isalpha() is true—

letterswhich are neither upper case nor lower case.


//stacktp.h -- a stack template


template<typenameType>

classStack

{

private:

enum{MAX= 10}; // constant specific to class

Typeitems[MAX];// holds stack items

inttop;// index for top stack item

public:

Stack();

boolisempty();

boolisfull();

boolpush(constType& item); // add item to stack

boolpop(Type& item); // pop top into item

};


template<typenameType>

Stack<Type>::Stack()

{

top= 0;

}


template<typenameType>

boolStack<Type>::isempty()

{

returntop == 0;

}


template<typenameType>

boolStack<Type>::isfull()

{

returntop == MAX;

}


template<typenameType>

boolStack<Type>::push(constType& item)

{

if(top <MAX)

{

items[top++]= item;

returntrue;

}

else

returnfalse;

}


template<typenameType>

boolStack<Type>::pop(Type& item)

{

if(top >0)

{

item =items[--top];

returntrue;

}

else

returnfalse;

}


主程序:

//stacktem.cpp -- test template stack class

//compiler with strng2.cpp

#include<iostream>

usingnamespacestd;

#include<cctype>

#include"stacktp.h"

#include"strng2.h"

intmain()

{

Stack<String>st;// create an empty stack

charc;

Stringpo;

cout <<"Please enter A to add a purchaseorder,\n"

<<"Pto process a PO, or Q to quit.\n";

while(cin >> c &&toupper(c)!='Q') //toupper将字符转化为大写

{

while(cin.get() != '\n')

continue;

if(!isalpha(c))//isalpha判断是不是字母

{

cout <<'\a';

continue;

}

switch(c)

{

case'A':

case'a': cout<< "Enter a PO number to add:";

cin>> po;

if(st.isfull())

cout<<"stack already full\n";

else

st.push(po);

break;

case'P':

case'p':if(st.isempty())

cout<<"stack already empty\n";

else{

st.pop(po);

cout<<"PO #"<< po <<" popped\n";

break;

}

}

cout <<"Please enter A to add a purchaseorder,\n"

<<"P to process a PO, or Q toquit.\n";

}

cout <<"Bye\n";

return0;

}


**************************************************************************

以下是几种template的使用:


把一个类定义成不受限制的template类型,对函数进行friend,这时此函数可以直接访问类的似有成员,并使用构造函数进行构造,其结果将根据参数类型的不同而不同!


//manyfrnd.cpp -- unbound template friend to a template class

#include<iostream>

usingnamespacestd;


template<typenameC>

classManyFriend

{

private:

Citem;

public:

ManyFriend(constC &i) : item(i){}

template<typenameE,typenameF>friendvoidshow2(E&,F&);

};


template<typenameE,typenameF>voidshow2(E& c, F& d)

{

cout <<c.item <<", "<< d.item << endl;

}


intmain()

{

//以下5行是我加的

chari[] ="a";

charj[] ="b";

ManyFriend<char>hfi3(i[0]);

ManyFriend<char>hfi4(j[0]);

show2(hfi3,hfi4);


ManyFriend<int>hfi1(10);

ManyFriend<int>hfi2(20);

ManyFriend<double>hfd(10.5);

show2(hfi1,hfi2);

show2(hfd,hfi2);


return0;

}

输出结果:


10,20

10.5,20


**************************************************************************


template的类friendtemplate的函数:


由于函数本身也是template类型的,所以在调用的时候会根据传入的参数类型不同得到不同的结果。

ct在其中代表一个计数值。这里可以和下面一个例子作比较,可以看到函数体中写的相对简单,传入参数不同就会有变化!


//tmp2tmp.cpp -- template friends to a template class

#include<iostream>

usingnamespacestd;


//template prototypes

template<typenameT>voidcounts();

template<typenameT>voidreport(T&);


//template class

template<typenameTT>

classHasFriendT

{

private:

TTitem;

staticintct;

public:

HasFriendT(constTT &i) : item(i){ct++;}

~HasFriendT(){ct--;}

friendvoidcounts<TT>();

friendvoidreport<>(HasFriendT<TT>&);

};


template<typenameT>

intHasFriendT<T>::ct= 0;


//template friend functions definitions

template<typenameT>

voidcounts()

{

cout <<"template counts(): "<<HasFriendT<T>::ct

<<endl;

}


template<typenameT>

voidreport(T& hf)

{

cout <<hf.item << endl;

}


intmain()

{

counts<int>();

HasFriendT<int>hfi1(10);

HasFriendT<int>hfi2(20);

HasFriendT<double>hfd(10.5);

report(hfi2);// generate report(HasFriendT<int>&)

report(hfd);// generate report(HasFriendT<double>&)

counts<double>();

counts<int>();


return0;

}


输出结果:

templatecounts(): 0

20

10.5

templatecounts(): 1

templatecounts(): 2


下面是一个templatefriendnon_template函数的例子:



因为函数不是template,所以在函数中针对不同类型做不同的实现。

由此可见template的优点!!


//frnd2tmp.cpp -- template class with non-template friends


#include<iostream>

usingnamespacestd;


template<typenameT>

classHasFriend

{

private:

Titem;

staticintct;

public:

HasFriend(constT &i) : item(i){ct++;}

~HasFriend() {ct--;}

friendvoidcounts();

friendvoidreports(HasFriend<T>&);// template parameter

};


//each specialization has its own static data member

template<typenameT>

intHasFriend<T>::ct= 0;


//non-template friend to all HasFriend<T> classes

voidcounts()

{

cout <<"int count: "<<HasFriend<int>::ct<< endl;

cout <<"double count: "<<HasFriend<double>::ct<< endl;

}


//non-template friend to the HasFriend<int> class

voidreports(HasFriend<int>& hf)

{

cout<<"HasFriend<int>: "<< hf.item<< endl;

}


//non-template friend to the HasFriend<double> class

voidreports(HasFriend<double>& hf)

{

cout<<"HasFriend<double>: "<< hf.item<< endl;

}


intmain()

{

counts();

HasFriend<int>hfi1(10);

HasFriend<int>hfi2(20);

HasFriend<double>hfd(10.5);

reports(hfi2);

reports(hfd);

counts();


return0;

}


***************************************************************************

template类作为另一个类的私有成员


//tempmemb.cpp -- template members

#include<iostream>

usingnamespacestd;


template<typenameT>

classbeta

{

private:

template<typenameV>// nested template class member

classhold

{

private:

Vval;

public:

hold(Vv = 0) : val(v){}

voidshow()const{ cout << val<< endl; }

VValue()const{returnval; }

};

/*

//template<typenameV> //或者也可以在类中声明这个成员,然后在外面实现!

//classhold;

*/

hold<T>q;// template object,这里使用了嵌入类生成的object

hold<int>n;// template object

public:

beta(T t,inti) :q(t),n(i) {}

template<typenameU>// template method

Ublab(Uu,Tt) {return(n.Value()+q.Value())* u / t; }

voidShow()const{q.show();n.show();}

};


/*上面的声明在这里实现:


//member definition

template<typenameT>

template<typenameV>

classbeta<T>::hold

{

private:

Vval;

public:

hold(Vv = 0) : val(v){}

voidshow()const { cout <<val<< endl; }

VValue()const { return val;}

};

*/


intmain()

{

beta<double>guy(3.5, 3);

guy.Show();

cout <<guy.blab(10, 2.3) << endl;

//此处n.Value= 3q.Value= 3.5, u = 10, t = 2.3, 返回u的类型为整形

//(((3+3.5*10/2.3=28.26

cout <<"Done\n";

return0;

}


********************************************************************


用一个类作为这个类的一种参数类型,所以在main函数中,用stack类的类型生成了一个Crab类的object,这样他最终调用的是stack类里面的pushpop


usingnamespacestd;

#include"stacktp.h" //这个看下面,同c++02中的一样,看看前面吧!!区别是template的方式


template<template<typenameT>classThing>//stack需要对应尖括号中的类型

classCrab

{

private:

Thing<int>s1;

Thing<double>s2;

public:

Crab(){};

// assumes the thing class has push() and pop() members

//这里实际上调用stack类中的pushpop

boolpush(inta,doublex) {returns1.push(a)&&s2.push(x);}

boolpop(int& a, double& x){returns1.pop(a)&&s2.pop(x);}

};


intmain()

{

Crab<Stack>nebula;

//Stack must match template <typename T> class thing

intni;

doublenb;


while(cin>> ni >> nb && ni > 0 && nb >0)

{

if(!nebula.push(ni, nb))

break;

}


while(nebula.pop(ni, nb))

cout <<ni <<", "<< nb << endl;

cout <<"Done.\n";


return0;

}


下面是stack类的定义方式,注意尖括号中是为了对应上面的template<typename T> class thing,才能在生成crabobject时使用!!!!


template<classType>

classStack

{

private:

enum{MAX= 10}; // constant specific to class

Typeitems[MAX];// holds stack items

inttop;// index for top stack item

public:

Stack();

boolisempty();

boolisfull();

boolpush(constType& item); // add item to stack

boolpop(Type& item); // pop top into item

};


template<classType>

Stack<Type>::Stack()

{

top= 0;

}


template<classType>

boolStack<Type>::isempty()

{

returntop == 0;

}


template<classType>

boolStack<Type>::isfull()

{

returntop == MAX;

}


template<classType>

boolStack<Type>::push(constType& item)

{

if(top <MAX)

{

items[top++]= item;

returntrue;

}

else

returnfalse;

}


template<classType>

boolStack<Type>::pop(Type& item)

{

if(top >0)

{

item =items[--top];

returntrue;

}

else

returnfalse;

}