c++——类模板

c++——类模板1 概念类模板 一个模板 是模板 模板类 调用类模板生成的类对象 是类实体 也称为类模板的实例化类模板的定义 template typenameT classBlob public Blob Blob std initializer list T i 类模板的使用 在定义类时 使用到类名的地方都需要显示的给出模板类的类型 格式为 lt gt intmain Blob T typenameT

1. 概念

  • 类模板:一个模板(是模板)
  • 模板类:调用类模板生成的类对象(是类实体),也称为类模板的实例化

类模板的定义:

template 
   
     class Blob { public: Blob(); Blob(std::initializer_list 
    
      i); }; 
     
   

类模板的使用:

  • 在定义类时,使用到类名的地方都需要显示的给出模板类的类型,格式为<>
int main() { Blob 
   
     ia; Blob 
    
      ia2 = { 1,2,3 }; Blob 
     
       * ia4 = new Blob 
      
        { 1.1,3.14 }; Blob 
       
         ia3 = { "Hello","World" }; return 0; } 
        
       
      
     
   

2. 模板类的成员函数

  • 如果模板类的成员函数在类内声明,而在类外定义,需要遵循以下规则:在函数前也在加上模板列表,且类名限定符后面给出<>
template 
  
    class Blob { public: Blob(); Blob(std::initializer_list 
   
     i); T func(T const &str);//在类内声明 }; //类外定义 template 
    
      T Blob 
     
       ::func(T const &str) { } 
      
     
    
  

类模板中使用其他模板类型

template 
   
     class Blob{ template 
    
      Blob(It b, It e);//构造函数的参数使用其它模板类型 }; template 
     
       template 
      
        Blob 
       
         ::Blob(It b, It e):data(std::make_shared 
        
          >(b,e)) { } int main() { vector 
         
           vi = { 0,1,2 }; list 
          
            w = { "Hello","World" }; Blob 
           
             a1(vi.begin(), vi.end()); Blob 
            
              a2(w.begin(), w.end()); return 0; } 
             
            
           
          
         
        
       
      
     
   

3. 友元:类模板中的友元

  • 一个类模板中也可以拥有友元(友元类/友元函数)
  • 下面只有当与Blob类型相同的BlobPtr类和operator==函数才可以成为Blob模板类的友元
template 
  
    class BlobPtr; template 
   
     class Blob; template 
    
      bool operator==(const Blob 
     
       &, const Blob 
      
        &) { } template 
       
         class Blob { friend class BlobPtr 
        
          ; //使BlobPtr模板类成为Blob模板类的友元 friend bool operator==(const Blob 
         
           &, const Blob 
          
            &);//使operator函数成为Blob模板类的友元 }; template 
           
             class BlobPtr { }; 
            
           
          
         
        
       
      
     
    
  

4. 友元:通用和特定的模板友元关系

  • 模板有需要复杂的关系,下面列出两个实例
template 
  
    class Pal; class C { friend class Pal 
   
     ; //用类C实例化的Pal是C的友元 template 
    
      friend class Pal2; //Pal2的所有实例都是C的友元 }; 
     
    
  
template 
  
    class C2 { friend class Pal 
   
     ; //与C2相同类型的实例化Pal才是C2的友元 template 
    
      friend class Pal2;//任何类型实例化的Pal2对象都是C2的友元,因为模板参数列表不同 friend class Pal3;//Pal3是一个非模板类,它是所有类型C2实例化的友元 }; 
     
    
  

5. 类模板的static成员

  • 与任何其他类一样,类模板可以声明static成员
  • 例如:下面Foo类模板中定义了一个static函数和static变量
template 
  
    class Foo { public: static std::size_t count() { return ctr; } private: static std::size_t ctr; }; 
  
  • 因为类的static成员变量只可在类内定义,在类外初始化。所以模板来的static变量也要在类外初始化,初始化时需要加上模板参数列表,例如下面代码,当一个特定的模板实例化Foo时,其ctr被初始化为0
template 
  
    std::size_t Foo 
   
     ::ctr = 0; //定义并初始化 
    
  
  • 静态成员的调用
Foo 
  
    fi; //实例化Foo 
   
     类和static数据成员ctr auto ct=Foo 
    
      ::count();//实例化Foo 
     
       ::count ct=fi.count(); //使用Foo 
      
        ::count,与上面的意义是相同 ct=Foo::count(); //错误,Foo没有指出使用哪个模板实例化 
       
      
     
    
  
  • 类模板的static成员的特点:当一个类给出模板实例化之后,与这个类实例化类型相同的类共享一样的静态成员
Foo 
  
    f1,f2,f3; //f1,f2,f3共享Foo 
   
     ::count()和Foo 
    
      ::str 
     
    
  

6. 使用类的成员函数(::符号)

引入:

  • 当我们通过作用域符访问的名字是类型还是static成员,编译器会自动识别,例如:
string::size_type //编译器知道我们要访问string类中的size_type数据类型
  • 但是对于模板就不能使用这种方法了,例如:
//编译器不知道size_type是一个static数据成员还是一种数据类型,因此产生二义性 T::size_type * p;
  • 默认情况下,C++语言假定通过作用域运算符访问的名字不是数据类型,而是数据成员。所以如果我们希望使用一个模板类型参数的类型成员,就必须显式地告诉编译器改名字是一个类型。需要通过typename来实现这一点
  • 例如下面的top函数:
template 
   
     typename T::value_type top(const T&c) { if (!c.empty()) return c.back(); else return typename T::value_type(); } 
   

c++——类模板

7. 成员模板

  • 一个类可以包含模板类型的成员函数,这种成员称为“成员模板”
  • 注意:成员模板不能为虚函数

①普通(非模板)类的成员模板

  • 概念:我们可以在一个非模板类中定义一个成员模板

演示案例

  • 默认的情况下,unique_ptr会调用元素的析构函数来删除元素。下面我们定义了一个删除器,删除器使用operator()接收一个元素指针,并将该元素进行delete
//函数对象类,对给定指针执行delete class DebugDelete { public: DebugDelete(std::ostream &s=std::cerr):os(s){} //构造函数 //根据传入的参数进行delete template 
   
     void operator()(T* p)const //成员模板 { os << "deleting unique_ptr" << endl; delete p; } private: std::ostream &os; }; 
   

 下面是基本的使用格式: 

int main() { double *p = new double; DebugDelete d; d(p); //调用DebugDelete::operator()(double*)释放p int *ip = new int; DebugDelete()(ip); //在一个临时DebugDelete对象上调用operator()(int*) return 0; }

 下面我们将这个类作为unique_ptr的删除器来使用

int main() { //一个类型为int的unique_ptr对象,DebugDelete作为其删除器 unique_ptr 
   
     p(new int, DebugDelete()); //一个类型为string的unique_ptr对象,DebugDelete作为其删除器 unique_ptr 
    
      sp(new std::string, DebugDelete()); return 0; } 
     
   

②类模板的成员模板

  • 概念:对于类模板,我们也可以为其定义成员模板。在此情况下,类和成员各自有自己的、独立的模板参数

演示案例

  • 例如下面Blob是一个类模板,模板类型为T数据成员vector的类型也为T。另外其构造函数也是一个模板,其接受的模板类型为It
template 
   
     class Blob { public: template 
    
      Blob(It b, It e); //构造函数接受一个迭代器区间,用来初始化data private: std::vector 
     
       data; }; 
      
     
   
  • 现在我们在类的外部定义构造函数,由于类模板与成员函数都是模板,因此在外部定义时需要分别同时给出这两个模板的模板参数列表
  • 实例化成员模板:为了实例化一个类模板的成员模板,我们必须同时提供类和函数模板的实参。见下面的演示案例,其中:
  • a1:Blob的类型为int,构造函数的类型为int*
  • a2:Blob的类型为int,构造函数的类型为vector

    ::iterator
  • a3:Blob的类型为string,构造函数的类型为list

    ::iterator
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/227018.html原文链接:https://javaforall.net

(0)
上一篇 2026年3月16日 下午10:08
下一篇 2026年3月16日 下午10:08


相关推荐

  • RapidXml 简介

    RapidXml 简介2019独角兽企业重金招聘Python工程师标准>>>…

    2022年7月17日
    18
  • delphi网页数据抓取

    delphi网页数据抓取简单 IdHttp TIdHttp Params TStrings BeginParams TStrinList Create IdHttp TIdHttp Create Nil 提交网页的参数 Params Add 参数 1 XXX

    2026年3月18日
    2
  • aircrack和reaver破解路由器PIN码

    aircrack和reaver破解路由器PIN码使用aircrack,寻找附近开启wps的路由器,邪恶……嘻嘻airmon-ng start wlan0airodump-ng mon0CH 11 ][ Elapsed: 36 s ][ 2012-12-18 04:46                                          BSSID              PWR  Beacons    #Data

    2022年5月5日
    109
  • jeesit框架通过jBox获取弹窗信息

    jeesit框架通过jBox获取弹窗信息需求 界面点击选择弹出窗口查询列表 选择后回填给父界面 按钮界面 使用 jBox 方式 弹窗 functionopen id varlevel level val 参数传给 iframe 界面查询使用 由于是弹出的面板 所以要自己写一个 jsp 一个单独的查询界面嵌入 iframe top jBox open iframe xx

    2026年3月17日
    2
  • 循环队列的元素个数计算公式是什么_队列求元素个数

    循环队列的元素个数计算公式是什么_队列求元素个数因为循环对列,rear不一定比front大如果rear<front结果是rear-front+maxsize如果rear>front结果是rear-front为了用一个表达式同时表达两者,用(rear-front+maxsize)%maxsize假设maxsize=10rear=1front=9,那么结果是2rear=9front=1,那么结果是8…

    2025年7月18日
    6
  • 基于HibernateTemplate关于Hibernate 增删改查

    基于HibernateTemplate关于Hibernate 增删改查转自 微点阅读 https www weidianyuedu comHibernate 增删改查 packagecom abin ssh bean importjava util List importorg apache commons logging Log importorg apache commons logging LogFactory importorg hibernate LockMode importorg springframew co

    2026年3月18日
    1

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号