模板特化

在将萃取机制之前,先要说明模板特化

当有两个模板类,一个是通用泛型模板,一个是特殊类型模板,如果创建一个特殊类型的对象,会优先调用特殊的类型模板类,例如:

template <typename T>	//泛型模板
class MyClass
{
public:
MyClass()
{
cout << "T MyClass!" << endl;
}
~MyClass()
{
cout << "~T MyClass!" << endl;
}
}; template<>
class MyClass<int> //全特化模板
{
public:
MyClass()
{
cout << "int MyClass!" << endl;
}
~MyClass()
{
cout << "~int MyClass!" << endl;
}
}; int main()
{
MyClass<char> mc0;
MyClass<int> mc1;
return 0;
}

运行结果:

T MyClass!
int MyClass!
~int MyClass!
~T MyClass!

萃取机制

现在举一系列例子来说明萃取机制

现在有两个类,需要完成相同的功能GetSum返回求和值

//int类型
class IntArray
{
public:
IntArray()
{
a = new int[10];
for (int i = 0; i < 10; ++i)
{
a[i] = i + 1;
}
}
~IntArray()
{
delete[] a;
} int GetSum(int times) //对整数求和
{
int sum = 0;
for (int i = 0; i < 10; ++i)
sum += a[i];
cout << "int sum=" << sum << endl;
return sum * times;
}
private:
int *a;
}; //Float类型
class FloatArray
{
public:
FloatArray()
{
f = new float[10];
for (int i = 1; i <= 10; ++i)
{
f[i - 1] = 1.0f / i;
}
}
~FloatArray()
{
delete[] f;
}
float GetSum(float times) //对浮点数求和
{
float sum = 0.0f;
for (int i = 0; i < 10; i++)
sum += f[i];
cout << "float sum=" << sum << endl;
return sum * times;
}
private:
float* f;
};

我们可以看到,这样写代码冗余度很高,一部分功能比如GetSum函数,两个类都有,能不能用一个类完成?

先定义一个类,通过泛型,调用对应对象的GetSum函数得到结果。

template<class T>
class Apply
{
public:
float GetSum(T& t, float inarg)
{
return t.GetSum(inarg);
}
};

这种方法不能完全解决我们的问题(函数返回值和参数类型固定,就会导致异常),如何解决变化的输入输出参数?traits技术就能解决问题。

template<class T>	//可以什么都不用写,说明定义了一个模板类
class NumTraits
{}; //模板特化IntArray
template<>
class NumTraits<IntArray>
{
public:
typedef int resulttype;
typedef int inputargtype;
};
//模板特化FloatArray
template<>
class NumTraits<FloatArray>
{
public:
typedef float resulttype;
typedef float inputargtype;
}; template<class T>
class Apply2
{
public:
NumTraits<T>::resulttype GetSum(T& obj, NumTraits<T>::inputargtype inputarg)
{
return obj.GetSum(inputarg);
}
}; int main()
{
IntArray intary;
FloatArray floatary;
Apply2<IntArray> ai2; //采用萃取
Apply2<FloatArray> af2; //采用萃取
cout << "2整型数组的和3倍:" <<ai2.GetSum(intary,3) << endl; //返回整形
cout << "2浮点数组的和3.2倍:" << af2.GetSum(floatary,3.2f) << endl; //返回浮点型
return 0;
}

为什么两个类中都定义了resulttype和inputargtype,为什么要把返回类型、输入参数,都定义为相同的名称呢?因为为了编制模板类共同的调用接口做准备。

为了简化Apply2函数的定义形式,再次巧妙运用typedef进行定义,代码如下,与原始功能相同。

//泛型模板类
template<class T>
class NumTraits
{}; //可以什么都不用写,说明定义了一个模板类 template<> //模板特化
class NumTraits<IntArray>
{
public:
typedef int resulttype;
typedef int inputargtype;
}; template<> //模板特化
class NumTraits<FloatArray>
{
public:
typedef float resulttype;
typedef float inputargtype;
}; template<class T>
class Apply2
{
public:
typedef NumTraits<T>::resulttype result;
typedef NumTraits<T>::inputpara input; result GetSum(T& obj, intput inputarg)
{
return obj.GetSum(inputarg);
}
};

总结

萃取机制在STL中被广泛运用,借助模板特化和和typedef可以将接口做到通用,降低了代码的冗余度,提高了代码的复用

最新文章

  1. PHP build notes - WARNING: This bison version is not supported for regeneration of the Zend/PHP parsers (found: 3.0, min: 204, excluded: 3.0).
  2. SDN与NFV技术在云数据中心的规模应用探讨
  3. python 调用封装好的模块
  4. 在VMware8.0.4安装centos6.3出现蓝屏,显示“anaconda: Fatal IO error 104 (Connection reset by peer) on X server :1.0. install exited abnormally [1/1]”?
  5. 双击防止网页放大缩小HTML5
  6. Android EditText输入最大值提示功能
  7. 找出linux服务器IO占用高的程序
  8. selenium ide 录制回放link链接报错
  9. 算法 python实现(三) 快速排序
  10. 登录模块需要用到session留底
  11. CUDA 编程
  12. 二叉搜索树与双向链表(python)
  13. JDK常用命令(三)jmap
  14. Redis 简介(官方翻译)
  15. Maven项目打包,Jar包不更新的问题
  16. Java 基本语法---Java数组
  17. 去掉JAVA部分依赖的事例
  18. python数据结构之链表(一)
  19. html5中高德、腾讯、百度 地图api调起手机app
  20. MVC下载远程文件流(WebClient)

热门文章

  1. Tomcat指定特定的java
  2. tensorflow数据集加载
  3. ABS与PC材质
  4. 0013 基于DRF框架开发(01 基类视图 APIView)
  5. CentOS虚拟机挂载U盘
  6. LayIM聊天框全屏根据浏览器高宽自适应
  7. thinkphp3.2短信群发项目实例
  8. php 爬虫采集
  9. 15. 3Sum、16. 3Sum Closest和18. 4Sum
  10. windows下安装配置subline+Markdown