C++类模板(泛型编程二)
来源:互联网 发布:苏轼 柳永 知乎 编辑:程序博客网 时间:2024/05/21 09:23
1.类模板定义
a.类模板以相同的方式处理不同的类型;
b.在类声明前使用template进行标识。
2.类模板语法规则
template <typename T>class Operator{public: T op(T a, T b);};<typename T> 用于说明类中使用的泛指类型T。
a.和函数模板不同,类模板只能显示指定具体类型,无法自动推导;定义对象时要加<type>
指定具体类型,如下所示。
Operator<int> op1;Operator<string> op1;int i = op1.op(1, 2);string s = op2.op("Hello", "World!");
b.声明的泛指类型T可以出现在类模板的任意地方;
c.类模板必须定义在.h文件中;
d.且不能分开实现在不同的文件中。;
e.类模板外部定义的成员函数需要加上模板<>声明。
3.类模板的应用场景
类模板主要用于存储和组织数据元素的类;类中数据组织的方式和数据元素的具体类型无关;比如:数组类、链表类、Stack类、Queue类等。
C++中将模板的思想应用于类,使得类的实现不关注数据元素的具体类型,而只关注类所需要实现的功能。
4.编译器如何编译函数模板
编译器对类模板的处理方式和函数模板相同。
a.编译器根据类模板的具体类型产生不同的类;
b.编译器会对函数模板进行两次编译,首先在声明的地方对类模板代码本身进行编译,然后在使用的地方对参数替换后的代码进行编译。
5.类模板的使用
下面给出类模板的初步使用:
Operator.h
#ifndef _OPERATOR_H_#define _OPERATOR_H_template < typename T >class Operator{public: T add(T a, T b); T minus(T a, T b); T multiply(T a, T b); T divide(T a, T b);};template < typename T >T Operator<T>::add(T a, T b){ return a + b;}template < typename T >T Operator<T>::minus(T a, T b){ return a - b;}template < typename T >T Operator<T>::multiply(T a, T b){ return a * b;}template < typename T >T Operator<T>::divide(T a, T b){ return a / b;}#endif
main.cpp
#include <iostream>#include <string>#include "Operator.h"using namespace std;int main(){ Operator<int> op1; cout << "op1.add(1, 2) = " << op1.add(1, 2) << endl; cout << "op1.multiply(4, 5) = " << op1.multiply(4, 5) << endl; cout << "op1.minus(5, 6) = " << op1.minus(5, 6) << endl; cout << "op1.divide(10, 5) = " << op1.divide(10, 5) << endl; return 0;}
运行结果如下所示:
6.多参数类模板
类模板可以定义任意多个不同的类型参数, 如下所示:
template <typename T1, typename T2>class Test {public: void add(T1, a, T2 b);};Test<int, float> t; // 定义对象
7.类模板特化
类模板可以被特化:
a.指定类模板的特定实现;
b.部分类型参数必须显示指定,比如返回值类型必须显示指定;
c.根据类型参数分开实现类模板。
d.类模板的特化可以分为:
部分特化:用特定规则约束类型参数;
完全特化:完全显示指定类型参数。
e.模板特化注意事项:
特化只是模板的分开实现 ,本质上是同一个类模板;
特化模板的使用方式是统一的,必须显示指定每一个类型参数。
下面给出模板特化的示例:
#include <iostream>#include <string>using namespace std;template < typename T1, typename T2 >class Test{public: void add(T1 a, T2 b) { cout << "void add(T1 a, T2 b) = " << a + b << endl; //cout << a + b << endl; }};template < typename T1, typename T2 >class Test < T1*, T2* > // 关于指针的特化实现{public: void add(T1* a, T2* b) { cout << "void add(T1* a, T2* b) = " << *a + *b << endl; //cout << *a + *b << endl; }};template < typename T >class Test < T, T > // 当 Test 类模板的两个类型参数完全相同时,使用这个实现{public: void add(T a, T b) { cout << "void add(T a, T b) = " << a + b << endl; //cout << a + b << endl; } void print() { cout << "class Test < T, T >" << endl; }};template < >class Test < void*, void* > // 当 T1 == void* 并且 T2 == void* 时{public: void add(void* a, void* b) { cout << "void add(void* a, void* b)" << endl; cout << "Error to add void* param..." << endl; }};int main(){ Test<int, float> t1; Test<long, long> t2; Test<void*, void*> t3; t1.add(1, 2.5); t2.add(5, 5); t2.print(); t3.add(NULL, NULL); Test<int*, double*> t4; int a = 1; double b = 0.1; t4.add(&a, &b); return 0;}
运行结果如下图所示:
8.数值型参数
模板参数可以是数值参数(非类型参数),格式如下:
template <int N>class{public: static const int value = N; };
模板参数是在编译阶段被处理的单元,因此模板参数必须在编译阶段必须准确无误的唯一确定,下面列出数值型模板参数的限制:
1.变量不能作为模板参数;
2.浮点数不能作为模板参数;
3.类对象不能作为模板参数。
总之,一切在编译阶段无法确定的参数均不能作为模板参数。
下面是一道面试题:
用你觉得最高效的方法求1+2+3+...+N的值!
下面通过模板数值型参数给出解答:
#include <iostream>using namespace std;template <int N>class Sum{public: static const int value = Sum<N-1>::value + N;};template < >class Sum <1>{public: static const int value = 1;};int main(){ cout << "1+2+3+...+10 = " << Sum<10>::value << endl; cout << "1+2+3+...+100 = " << Sum<100>::value << endl; return 0;}
Sum::value的值在编译的时候就已经确定了,因此用此方法应该是最高效的了,下面为运行结果:
- linux c 编程模板总结(二)
- C++类模板(泛型编程二)
- C++泛型编程----(二)模板类
- C++模板与泛型编程(二)——类模板
- 【C/C++学院】(11)泛型编程/函数模板/类模板
- C++primer 阅读笔记-模板与泛型编程(类模板)
- 模板与泛型编程(二)--《C++ primer》
- C++ Primer 学习笔记_82_模板与泛型编程 -类模板成员[续二]
- C++ 之 模板与泛型编程(二、模板实例化)
- Effective C++(七)模板与泛型编程
- Effective C++(七)模板与泛型编程
- [C++] 模板与泛型编程(1)
- [C++] 模板与泛型编程(2)
- [C++]模板与泛型编程(3)
- C++Primer---模板与泛型编程(一)
- C++(7)模板与泛型编程
- C++(7)模板与泛型编程
- Pure C++: 泛型编程,模板特殊化
- HTTP和HTTPS
- ART(Android Runtime)和dalvik和jvm的解释和对比
- 在二叉树中找到一个节点的后继节点
- LayoutInflater 源码分析
- 硬件调试
- C++类模板(泛型编程二)
- 静态内部类的生命周期
- PAT B1059.C语言竞赛
- JS 解析JSON字符串 得到对象数组
- 锤子剪子布
- 带权并查集,经典-食物链,poj-1182
- Android Studio debug使用release的签名,省去微信登录之类的要打成正式包才能测试的麻烦!
- 【代码】 四法求逆元
- [数组]递归方式求和