Class Templates

本文深入讲解C++中的类模板概念,包括定义、使用、特化、偏特化及默认模板参数等内容,并通过实例演示如何创建和操作类模板。

一、class template定义

#include <vector>
#include <stdexcept>

template <typename T>
class Stack { 
private: 
   std::vector elems; 
public: 
   void push(const T&amp;); 
   void pop(); 
   T top() const; 
   bool empty() const { 
       return elems.empty(); 
   } 
}; 

template <typename T>
void Stack<T>::push(const T&amp; elem) 
{ 
     elems.push_back(elem); 
} 

template <typename T>
void Stack<T>::pop() 
{ 
    if (elems.empty()) 
    { 
         throw std::out_of_range(&quot;Stack::pop: empty stack&quot;); 
    } 
    elems.pop_back(); 
} 

template <typename T>
T Stack<T>::top() const 
{ 
    if (elems.empty()) 
    { 
        throw std::out_of_range(&quot;Stack::top: empty stack&quot;); 
    } 
    return elems.back(); 
} 

 
二、使用class template

#include <iostream> 
#include <string> 
#include <cstdlib> 
#include "stack1.hpp" 

int main() 
{ 
    try { 
        Stack<int>         intStack;       // stack of ints 
        Stack<std::string> stringStack;    // stack of strings 

        // manipulate int stack 
        intStack.push(7); 
        std::cout << intStack.top() << std::endl; 

        // manipulate string stack 
        stringStack.push("hello"); 
        std::cout << stringStack.top() << std::endl; 
        stringStack.pop(); 
        stringStack.pop(); 
    } 
    catch (std::exception const& ex) { 
        std::cerr << "Exception: " << ex.what() << std::endl; 
        return EXIT_FAILURE;  // exit program with ERROR status 
    } 
} 

 代码只有在成员函数被调用时才被具现化。针对类模板而言,成员函数只有在被使用时才会被具现化。如果类模板中包含有静态成员,那些静态成员针对类型只会被实具现化一次。通过类模板具现化的类使用起来与其他类型一样。

 

对类模板类型参数的唯一要求就是针对类型参数的任何调用必须满足。


三、模板特化

完全特化:特化类型将作为template parameter并在class名称之后直接写明。如

#include <deque> 
#include <string> 
#include <stdexcept> 
#include "stack.hpp" 

template<> 
class Stack<std::string> 
{ 
private: 
  std::deque<std::string> elems; 
public: 
  void push(const std::string&); 
  void pop(); 
  std::string top() const; 
  bool empty() const { 
     return elems.empty(); 
  } 
}; 

void Stack<std::string>::push(const std::string& elem) 
{ 
    elems.push_back(elem); 
} 

void Stack<std::string>::pop() 
{ 
   if (elems.empty()) 
   { 
       throw std::out_of_range("Stack<std::string>::pop(): empty stack"); 
   } 
   elems.pop_back(); 
} 

std::string Stack<std::string>::top() const 
{ 
    if (elems.empty()) 
   { 
       throw std::out_of_range("Stack<std::string>::pop(): empty stack"); 
   } 
   return elems.back(); 

} 

 当模板类针对某个类型参数进行特化时,模板类中的所有成员函数也必须同时提供特化实现。


四、模板偏特化
class template可以被偏特化,这使得在特定情形下使用特殊实现代码,但仍然留出选择template parameter的能力。

template <typename T1, typename T2> 
class MyClass { 
... 
}; 

//partial specialization: two template parameters are same 
template <typename T> 
class MyClass<T,T> { ... }; 

//partial specialization: 2nd template parameter is int 
template <typename T> 
class MyClass<T,int> { ... }; 

//partial specialization: two template parameters are pointers 
template <typename T1, typename T2> 
class MyClass<T1*, T2*> { ... }; 


五、默认模板参数

template <typename T, typename CONT=std::vector<T> > 
class Stack { 
private: 
   CONT elems; 
public: 
   void push(const T&); 
   void pop(); 
   T top() const; 
   bool empty() const { return elems.empty() } 
}; 

... 

 
使用带有默认模板参数时,如果与默认模板参数一致,不需要指定;否则需显式指定;如

Stack<double, std::deque<double> > 

 

六:非类型模板类型参数(NON-TYPE TEMPLATE PARAMETER)

 

非类型参数主要是指值参数而非类型参数,通常是常整数、枚举、或者指向带有外链接对象的指针,浮点数或者class-type对象是不允许作为非类型模板参数的。在使用时,这个非类型模板参数必须显式指定。

 

小结摘要:

1. 所谓class template是包含一个或者多个尚未确定类型的class。

2. 必须将具体数据类型当做template parameter传入,才能使用class template。 于是该class template才能按照给定的template parameter数据类型,由编译器具现化并编译。

3. class template中,只有实际被调用的成员函数,才会被具现化。

4. 可以针对某些特别类型,对class template进行特化

5. 也可以针对某些特定类型,对class template进行偏特化

6. 可以为template parameter定义默认值

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值