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,进栈或是出栈!主程序中简单的用while和switch对用户输入的命令,也就是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的类friend给template的函数:
由于函数本身也是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
下面是一个template类friend给non_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= 3,q.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类里面的push和pop
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类中的push和pop
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,才能在生成crab的object时使用!!!!
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;
}
- C++03_template
- 触发器_template
- java设计模式进阶_template-method
- 设计模式——模板模式_Template Pattern
- No.03 Xcode(5.1.x) c,c++,objiective-c混编
- C#note 03: string
- Effective C++:条款03
- Objective-C 03
- 03,标准C
- 49,C++(03)
- 标准C知识03
- C语言03
- c和指针 03
- Effective.C 读书笔记03
- C语言03数组
- C语言学习03
- 03、C语言-数组
- C语言03
- jQuery中的 return false, e.preventDefault(), e.stopPropagation()的区别
- 【PB】子数据窗的应用
- excel导入错误:外部表不是预期格式
- n个数进栈,随机出栈,不同顺序数 catalan number
- C++ 如何改写其他进程指定地址的内存
- C++03_template
- node.js xmlreader无法获取CDATA区问题修复
- mongodb sharding
- SOVA的实现(2)
- spring集合注入案例
- undefined reference to ‘raise’ //make distclean和make clean的作用
- Spring中的集合——List、Map、Set、Properties
- 宏do{}while(0)
- SAP发票校验前收货后是否能更改物料价格