C++ Primer 学习笔记_81_模板与泛型编程 --类模板成员[续1](二)

2014-11-24 13:11:06 · 作者: · 浏览: 7
&); friend istream & operator>> (istream &,Screen &); public: typedef std::string::size_type index; Screen(): screen(hi * wid,'#'),cursor(0),height(hi),width(wid) {} private: string screen; index cursor; index height,width; }; template ostream &operator<<(ostream &os,const Screen &s) { os << "screen: " << s.screen << "\t" << "height: " << s.height << "\t" << "width: " << s.width; return os; } template istream &operator>>(istream &in,Screen &s) { in >> s.screen >> s.height >> s.width; if (in) { s.cursor = s.height * s.width; } return in; }
//习题16.42
template 
  
   
istream &operator>>(istream &in,Queue
   
     &q) { Type item; in >> item; q.push(item); return in; } 
   
  


五、成员模板

任意类都可以拥有本身为类模板或函数模板的成员,这种成员称为成员模板,成员模板不能为虚。

考虑Queue类的复制构造函数:它接受一个形参,是Queue 的引用。想要 通过从 vector 对象中复制元素而创建 Queue 对象 , 是办不到的,因为没有从vector到 Queue的转换。类似地,想要 Queue 复制元素到 Queue , 也办不到。同样的逻辑应用于赋值操作符,它也接受一个Queue &类型的形参。

我们希望定义一个构造函数和一个 assign成员,使容器类型元素类型都能变化

在Queue例子中,我们将定义构造函数和 assign成员接受一对在其他序列指明范围的迭代器,这些函数将有一个表示迭代器类型模板类型形参

【注意】

标准queue类没有定义这些成员:不支持从其他容器建立queue对象或给 queue对象赋值。我们在这里定义这些成员只是为了举例说明



1、定义成员模板

模板成员声明看起来像任意模板的声明一样:

template 
  
    class Queue
{
public:
    //函数形参是指明要复制元素范围的迭代器
    template 
   
     Queue(Iter beg,Iter end):head(0),tail(0) { copy_elems(beg,end); } template 
    
      void assign(Iter,Iter); //As Before private: //As Before template 
     
       void copy_elems(Iter,Iter); }; 
     
    
   
  

2、在类外部定义成员模板

当在类外定义成员模板的时候,必须包含两个模板形参表:

1)assign成员:

//T:类模板形参;Iter:成员函数自己的模板形参
template 
  
    template
   
     void Queue
    
     ::assign(Iter beg,Iter end) { destroy(); copy_elems(beg,end); } 
    
   
  

2)copy_elems成员:

template 
  
    template
   
     void Queue
    
     ::copy_elems(Iter beg,Iter end) { while (beg != end) { push(*beg); ++ beg; } } 
    
   
  

【小心地雷】

因为assign函数删除现在容器中的成员,所以传给assign函数的迭代器有必要引用不同容器中的元素。标准容器的assign成员和迭代器构造函数有相同的限制。



3、成员模板遵循常规访问控制

成员模板遵循与任意其他类成员一样的访问规则。如果成员模板为私有的,则只有该类的成员函数和友元可以访问该成员模板。



4、成员模板和实例化

成员模板只有在程序中使用时实例化。只是类模板的成员模板实例化比类模板的普通成员函数的实例化要稍微复杂一些,成员模板有两种模板形参:由类定义的和由成员模板本身定义。其中:类模板形参由调用函数的对象的类型确定,成员定义的模板形参的行为与普通函数模板一样。这些形参都通过常规模板实参推断而确定。

理解下面一段程序:

    short a[4] = {0,3,6,9};
    Queue
  
    qi(a,a + 4);
    vector
   
     vi(a,a + 4); qi.assign(vi.begin(),vi.end()); 
   
  

qi的定义将实例化:

void Queue
  
   ::Queue(short *, short *);

  

qi的assign成员的实例化:

void Queue
  
   ::assign(vector
   
    ::iterator, vector
    
     ::iterator);