栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

解读C++编程中类模板的三种特化

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

解读C++编程中类模板的三种特化

1.类模板显式特化
为了进行特化,首先需要一个通用的版本,称主模板.主模板使用了标准库堆算法.  堆 是一种线性化的树形结构,将一个值压入一个堆中, 实际上等于将该值插入到一个树形结构中;将一个值从堆中取出就等于移除并返回堆中最大值.但在处理字符的指针时会碰钉子.堆将按照指针的值进行组织. 我们可以提供一个显式特化版本解决此问题(例1)如果希望除了一个针对const char*的Heap外,还希望提供一个针对char *的Heap;(例2)

//主模板
template 
class Heap
{
private:
  std::vector h_;
public:
  void push(const T& val);
  T pop();
  bool empty() const //const声明在末尾表示该函数不能修改类变量
  {
    return h_.empty();
  }
}

template 
void Heap::push(const T& val)
{
  h_.push_back(val);
  std::push_heap(h_.begin(),h_.end());
}

template 
T Head::pop()
{
  std::pop_head(h_.begin(),h_.end());
  T tmp(h_.back());
  h_.pop_back();
  return tmp;
}

例1

//显示特化版本

template<>//注意,无任何参数,当然,它本来就不是一个模板
class Head
{
private:
  std::vector h_;
public:
  void push(const char *pval);
  const char * pop();
  bool empty() const //const声明在末尾表示该函数不能修改类变量
  {
    return h_.empty();
  }
};
//再次提醒, Head不是一个模板
void Heap::push(const char *pval)
{
  h_.push_back(pval);
  std::push_heap(h_.begin(),h_.end());
}

例2


template<>//注意,无任何参数,当然,它本来就不是一个模板
class Head
{
private:
  std::vector h_;
public:
  void push(char *pval);
  char * pop();
  //注意,此处没有提供empty函数哟!!!
  size_t size() const;
  void capitalize();
};

2.模板局部特化
模板局部特化首先要声明的是,C++还不支持对函数模板的局部特化,所以此处我们只讨论类模板的局部特化.我们依然首先需要一个主模板.(参考类模板显式特化) 自我理解:如果针对不能的指针定义不同的完全特化,岂不是太麻烦了,有没有更好的办法呢?那就是局部特化了.(例1)提示: 局部特化它是一个模板.完全特化不是一样模板.

例1


template 
class Heap //注意这里
{
private:
  std::vectorh_;
public:
  void push(const T *val);
  T *pop();
  bool empty()
  {
    return h_.empty();
  }
};

template 
void Heap::push(const T *val)
{
  //......
}

例2


//定义一个模板,有三个模板参数,书写形式如下
template  
//注意,局部特化中,模板参数也是三个,但书写形式可不一样喽
class Heap
{
  //......
};

Heap h7; //R是char *,A1和A2是int
//把 char *(*) (int,int) 想象成一个"指向有两个参数的非成员函数的指针"

template 
class Heap
{
  //......
};
Heap h8;//T是string,C是Name

尽管为何需要对这些东西使用Heap只是一个猜测,先知道有这么一用法吧!

3.类模板成员特化

虽然模板的特化和类的派生之间没有任何关系, 但在特化模板的时候,不妨借鉴一下派生的精神.也就意味着一个完全特化或局部特化通常必须重新实现 主模板具备的所有能力.
例:

//主模板
template 
class Heap
{
private:
  std::vector h_;
public:
  void push(const T& val);
  T pop();
  bool empty() const //const声明在末尾表示该函数不能修改类变量
  {
    return h_.empty();
  }
}
//其实我们真正需要特化的是 push 和 pop两个函数.
//对比显式特化,它是通过主模板,再写一个模板显式特化版本类;
//而这里只是对类模板成员进行了单独特化.
template<>
void Heap::push(const char *const &pval)
{
  h_.push_back(pval);
  std::push_heap(h_.begin(),h_.end(),strLess);
}

template<>
const char* Heap::pop()
{
  std:pop_heap(h_.begin(),h_end(),strLess);
  const char* tmp = h_.back();
  h_.pop_back();
  return tmp;
}


注意,这些函数的接口必须和 "它们正在特化其成员" 的模板的相应接口相匹配.如例1, 就得和主模板的接口相匹配.而如果你是自己再定义的一个显式/局部特化版本类,就不需要匹配 一致.(见显式特化和局部特化),最后指出两点: 首先,除了成员函数外,其实成员也可以被显式特化,如静态成员和成员模板.其次,显式特化是为模板或模板成员提供定制版本的一种手段;而显式实例化仅仅是明确地告诉编译器去实例化一个成员.       

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/64648.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号