类模板

来源:互联网 发布:node.js 知乎 编辑:程序博客网 时间:2024/06/07 12:24

一.建立一个stack类

#include<iostream>
const int MAX=10;
using namespace std;
template<typename T>
class Stack
{
 private:
  T stack[MAX];
  int top;
 public:
  Stack()
  {
   top=0;
  }
  void push(T const &s);
  T& pop();
  T& GetTop() const;
  int IsEmpty() const ;
};
template<typename T>  //函数定义时别忘了带上这个
void Stack<T>::push(T const &s)
{
 stack[top++]=s;
}
template<typename T>
T& Stack<T>::pop()
{
 return stack[--top];
}
template<typename T>
T& Stack<T>::GetTop() const
 {
  return stack[top-1];
 }
template<typename T>
int Stack<T>::IsEmpty() const
{
 return top==0;
}
//主函数
int main(int argc,char **argv)
{
 Stack<int> s;
 for(int i=0;i<10;i++)
   s.push(i);
 while(!s.IsEmpty())
 {
  cout<<s.pop();
 }
 cout<<endl;
 return 0;
}

 

二.模板的特化(类模板不允许重载)

template<typename T1,typename T2>

class MyClass{...};

//局部特化:1

template<typename T>//注意特化的时候类后面加了<...>

class MyClass<T,T>{...};

//局部特化:2

template<typename T>

class MyClass<T,int>{...};

//局部特化:3

template<typename T1,typename T2>

class MyClass<T1*,T2*>{...};

(注意:特化的模板属于非特化模板的子集,即非特化的模板包含了所有特化的情况)

MyClass<int,float>mt=======>MyClass<T1,T2>

MyClass<int,int>mt=======>MyClass<T,T>

MyClass<float,int>mt====>MyClass<T,int>//优先考虑特化模板(其实非特化也满足)

MyClass<int*,float*>=======>MyClass<T1*,T2*>//同上

 

三.另外一个例子

#include<iostream>
using namespace std;
template<typename T1,typename T2>
class Myclass{
 private:
  T1 a;
  T2 b;
 public:
  Myclass(T1 m,T2 n)
  {
   a=m;
   b=n;
   cout<<"fun1 was called!"<<endl;
  }
};
//局部化1
template<typename T>
class Myclass<T,T>{
 private:
  T a;
  T b;
 public:
  Myclass<T,T>(T m,T n)
  {
   a=m;
   b=n;
   cout<<"fun2 was called!"<<endl;
  }
};
//局部特化2
template<typename T1>
class Myclass<T1,char>{
 private:
  T1 a;
  char b;
 public:
  Myclass<T1,char>(T1 m,char n)
  {
   a=m;
   b=n;
   cout<<"fun3 was called!"<<endl;
  }
};
//局部特化3
template<typename T1,typename T2>
class Myclass<T1*,T2*>{
 private:
  T1* a;
  T2* b;
 public:
  Myclass<T1*,T2*>(T1* m,T2* n)
  {
   a=m;
   b=n;
   cout<<"fun4 was called!"<<endl;
  }
};


int main(int argc,char *argv[])
{
   int a=1,*pa=&a;
   float b=2.3,*pb=&b;
   Myclass<int,float> s1(1,2.3);
   Myclass<int,char>  s2(1,'a');
   Myclass<int,int>   s3(1,2);
   Myclass<int *,float *> s4(pa,pb);
      return 0;
}
//g++ 4.6.1
//fun1 was called!
//fun3 was called!
//fun2 was called!
//fun4 was called!

 

四.模板的继承

1.非依赖基类,即基类的模板参数不依赖派生类的模板参数。

#include<iostream>
using namespace std;
template<typename T>
class A{
 private:
  T a;
 public:
  A(T m)
  {
   a=m;
  }
  void printa()
  {
   cout<<"A::a="<<a<<endl;
  }
};
template<typename T>
class B:public A<int>{
 private:
  T b;
 public:
  B(T n,int i):A<int>(i)
  {
   b=n;
  }
  void printb()
  {
   printa();
   cout<<"B::b="<<b<<endl;
  }
};

int main(int argc,char *argv[])
{
   A<float> a(1.5);
   B<int>   b(2,4);
   a.printa();
   b.printb();
      return 0;
}
//A::a=1.5
//A::a=4
//B::b=2

 
2.依赖基类,即基类的模板参数依赖于派生类的模板参数(注意:此时在派生类中调用基类的成员,要显式使用this指针或Base::作用域)

#include<iostream>
using namespace std;
template<typename T>
class A{
 private:
  T a;
 public:
  A(T m)
  {
   a=m;
  }
  void printa()
  {
   cout<<"A::a="<<a<<endl;
  }
};
template<typename T1,typename T2>
class B:public A<T2>{
 private:
  T1 b;
 public:
  B(T1 n,T2 m):A<T2>(m)
  {
   b=n;
  }
  void printb()
  {
   this->printa(); //这里要使用this指针
   cout<<"B::b="<<b<<endl;
  }
};

int main(int argc,char *argv[])
{
   B<int,int>   b1(2,4);
   B<int,float> b2(2,3.5);
   b1.printb();
   b2.printb();
      return 0;
}
//A::a=4
//B::b=2
//A::a=3.5
//B::b=2

 

四.模板参数小技巧
1.模板的参数还可以是非类型(注意:非类型不可以是浮点double和常量字符串指针)

template<typename T,int MAX>

class Stack{

private:

T stack[MAX];

......

public:

void push(..);

......

};

//在定义的时候:

template<typename T,int MAX>

void Stack<T,MAX>push(..){..};//直接带入MAX

2.模板的参数来定义类成员

template<typename T >

class Stack{

private:

typename T::iterator it;//当没有typename时T将被认为是静态成员

T stack[MAX];

......

public:

void push(..);

......

};

3.模板的参数还可有默认值
template<typename T= int>//默认值为int
class Stack{
private:
T stack[MAX];
......
public:
void push(..);
......
};

五.模板参数
1.成员函数模板不能声明为虚函数,因为虚函数的调用机制使用的大小固定的虚函数表。
2.模板参数还可以是类或函数模板
template<templateT,template<typename T1,typename T2> class A>
class B{
A<T,int>bb;
.....//注意这里不能再使用T1,T2了,如T1 data; (错误)
}

所以可以简化为
template<template T,template<typename ,typename > class A>
class B{
A<T,int> bb;
.....//注意这里不能再使用T1,T2了,如T1 data; (错误)
}
 3.缺省参数依赖于前面的模板参数
template<typename T,typename Allocator=allocator<T> >//注意这里空格
calssList;
......