C++模板实战2:模板类

2014-11-24 07:27:21 · 作者: · 浏览: 0

1 借助函数模板可以使算法脱于具体数据类型之外,借助模板类可以使数据结构脱于具体数据类型之外,从而专注于数据存取方法及数据间的关联方式,抽象的数据结构可以和具体数据类型无关。类模板和函数模板一样以template 开头,但是类模板实例化和函数模板实例化有一点不太一样,函数模板可以从函数参数自动推导模板参数从而可以省略模板参数的书写,而类模板即使有默认模板参数其<>还是不能省略,即最简单的类模板实例化也是类似于:class test<> one;其中采用默认模板参数可以省略参数单数<>不能省略。而且默认的模板参数尽量在安排在众模板参数的后面,因为模板实例化是按照参数位置来推导的。下面是一个简易的线程安全的栈操作(部分):

#include
  
   
#include
   
     #include
    
      #include
     
       using namespace std; template
      
        class myStack{//只提供了push和try_pop操作 public: myStack():head(nullptr){} myStack(myStack& one)=delete;//防止多个栈共享head myStack& operator=(const myStack& one)=delete; ~myStack(){ while(head){ node* temp=head->next; delete head; head=temp; } } void push(T& value){ node* new_node=new node(value); unique_lock
       
         lock(m); new_node->next=head; head=new_node; } bool try_pop(T& value){//栈内有元素则返回true,否则返回false,元素值通过函数参数引用返回 unique_lock
        
          lock(m); if(head){ value=move(*head->data); head=head->next; return true; } else{ return false; } } bool empty() const{ unique_lock
         
           lock(m); return head==nullptr true:false; } private: struct node{ shared_ptr
          
            data; node* next; node(T& value):data(std::make_shared
           
            (value)){} node():next(nullptr){} }; node* head; mutex m;//互斥量保护栈存取 }; int main(){ myStack
            
              stackOne; string s("hello world"); stackOne.push(s); string temp; if(stackOne.try_pop(temp)) cout<
              
              

2 模板与继承:若基类是模板类,子类必须指定基类的模板参数,可以如下:

template
               
                
class base;//模板基类

template
                
                  class derived1: public base
                 
                  ;//子类和基类使用共同的模板参数 template
                  
                    class derived2:public base
                   
                    ;//子类和基类模板参数不同 class derived3:public base
                    
                     ;//子类不是模板类,基类需实例化
                    
                   
                  
                 
                
               

3 模板类与成员函数:模板类的成员函数可以使用和类模板相同的模板参数,也可以使用不同于类模板的参数。成员函数类外实现时要注意带上类模板的参数。实例如下:

template
               
                 
class test{
  public:
      void fun(){cout<<"fun"<
                
                  void fun2(); }; template
                 
                  //和类模板参数一样且类外实现 void test
                  
                   ::fun1(){cout<<"fun1"<
                   
                    //类外实现注意带上类的模板参数 template
                    
                      void test
                     
                      ::fun2(){cout<<"fun2"<
                      
                       
4 类模板的静态成员:普通类中的静态成员在类的多次实例化对象中静态成员始终只有一份,在模板类中静态成员是否如此呢?首先模板类实例化后具有相同模板参数的实例化才是同样的类,那么相同的模板实例化代码共享同一份静态数据成员。如下:

template
                        
                         
class test{   
   public:
       staitc int data;
};
template
                         
                           int test
                          
                           ::data=0;//静态成员的类外初始化 test
                           
                             one; test
                            
                              two;//one和two实例化后共享data的内存地址 test
                             
                               three;
                             
                            
                           
                          
                         
                        

5 友元模板类:友元耦合性太强,一般不怎么用,要用友元类模板可以如下:

template
                        
                         
class test;

class one{
   public:
       template
                         
                           friend class test; };
                         
                        

6 嵌套模板实现tuple:std::pair表示一个二元组,tuple可以表示多元元组,C++11通过变长模板实现std::tuple,变长模板对模板参数包的解包对变长模板参数解析。这里通过嵌套实现tuple,代码如下:

#include
                        
                         
#include
                         
                           using namespace std; template
                          
                            struct Tuple{ T value; N next; Tuple(T const& v,N const& n):value(v),next(n){} }; template
                           
                             Tuple
                            
                              push(T const& v,N const& n){ return Tuple
                             
                              (v,n); } int main(){ using Tuple2=Tuple
                              
                               ; using Tuple3=Tuple
                               
                                ; using Tuple4=Tuple
                                
                                 ; Tuple4 myTuple=push(string("PI"),push(3.14f,push(1,'p'))); cout<
                                 
                                  程序输出: 
                                  

PI 3.14 1 p