当前位置:网站首页>STL 笔记(二):模板、操作符重载
STL 笔记(二):模板、操作符重载
2022-07-19 18:17:00 【Reyn Morales】
STL 笔记(二):模板、操作符重载
模板
模板特化(具体化)
#include <iostream>
#include <cstring>
using namespace std;
// 统计数组中有多少个2 - 迭代器相关
int count(int * start, int * over, int n) {
int countNum = 0;
while (start < over) {
if (*start == n) countNum++;
start++;
}
return countNum;
}
// 函数模板 - 输出两个数中的最大值
template <typename T>
T MyMax(T a, T b) {
return a > b ? a : b;
}
// 模板特化(具体化)
template <>
char * MyMax(char * a, char * b) {
if (strcmp(a, b) > 0) return a;
return b;
}
// 类模板 - 两数之和
template <typename T>
class Add {
private:
T a;
T b;
public:
Add(T sa, T sb) {a = sa, b = sb;};
void show() {cout << a + b << endl;};
};
// 模板特化(具体化)
template <>
class Add<char *> {
private:
char * a;
char * b;
public:
Add(char * sa, char * sb) {strcpy(a, sa), strcpy(b, sb);};
void show() {cout << strcat(a, b) << endl;};
};
int main()
{
// 统计数组中有多少个2
int a[] = {2, 2, 4, 5, 2}; // 容器
int * start = a; // 迭代器 - 开始
int * over = a + sizeof(a) / sizeof(int); // 迭代器 - 结束
cout << count(start, over, 2) << endl;
// 输入两个数中的最大值
cout << MyMax(2, 3) << endl;
cout << MyMax(2.2, 3.3) << endl;
cout << MyMax("Relax", "Reyn") << endl;
// 两数之和
Add<int> firstNums(2, 3);
firstNums.show();
Add<double> secondNums(2.2, 3.3);
secondNums.show();
char * str1 = "Reyn";
char * str2 = "Relax";
Add<char *> strs(str1, str2);
strs.show();
return 0;
}
萃取 (traits)
#include <iostream>
using namespace std;
// traits技术:提取不同类的共性,以便统一处理
// 1. 定义基本类模板
template <typename T>
class PlusTras {};
// 2. 模板特化
template <>
class PlusTras<int>
{
public:
typedef int R;
};
template <>
class PlusTras<double>
{
public:
typedef double R;
};
template <>
class PlusTras<char>
{
public:
typedef int R;
};
// 3. 统一模板调用类编制
template <typename T>
typename PlusTras<T>::R Plus(T a, T b)
{
return a + b;
}
/*
typename:
1. 与class等价,用于声明模板参数
2. 模板中标识 “内嵌依赖类型名”
a. 内嵌指定义在某个类中
b. 依赖指依赖于某个模板参数
c. 类型名指表示的是数据类型名,而不是变量名
*/
class INT {
int a[3];
public:
INT(int sa[]) {for (int i = 0; i < 3; i++) a[i] = sa[i];}
int Sum() {
int s = 0;
for (int i = 0; i < 3; i++) s += a[i];
return s;
}
};
class DOUBLE {
double a[3];
public:
DOUBLE(double sa[]) {for (int i = 0; i < 3; i++) a[i] = sa[i];}
double Sum() {
double s = 0;
for (int i = 0; i < 3; i++) s += a[i];
return s;
}
};
class CHAR {
char a[3];
public:
CHAR(char sa[]) {for (int i = 0; i < 3; i++) a[i] = sa[i];}
int Sum() {
int s = 0;
for (int i = 0; i < 3; i++) s += a[i];
return s;
}
};
template <typename T>
class MyTraits {};
template <>
class MyTraits<INT>
{
public:
typedef int R;
};
template <>
class MyTraits<DOUBLE>
{
public:
typedef double R;
};
template <>
class MyTraits<CHAR>
{
public:
typedef int R;
};
template <typename T>
class Manage // 统一模板调用类
{
public:
typename MyTraits<T>::R Sum(T t) {return t.Sum();}
};
int main()
{
cout << Plus(4, 5) << endl;
cout << Plus(4.2, 5.8) << endl;
cout << Plus('Q', 'R') << endl;
int a[] = {1, 2, 3};
char b[] = {'h', 'y', 'i'};
double c[] = {3.3, 5.2, 4.4};
INT in(a);
CHAR ch(b);
DOUBLE dou(c);
Manage<INT> m1; // Manage<INT> 也是一种类型
cout << m1.Sum(in) << endl; // 通过统一接口调用了共性的方法,Sum()是所有复合类型的共性操作,但实现不同
Manage<CHAR> m2; // Manage<CHAR> 也是一种类型
cout << m2.Sum(ch) << endl; // 对象(ch)决定方法,返回类型的控制由复合类型(Manage<CHAR> m2)决定
Manage<DOUBLE> m3; // Manage<DOUBLE> 也是一种类型
cout << m3.Sum(dou) << endl; // 若存在另一个DOUBLE类型的对象(fuk),显然可以使用 m3.Sum(fuk)
return 0;
}
主要目标
提取不同类的共性,以便统一处理
核心思想
traits 依靠显式模板特殊化来把代码中因类型不同而发生变化的片段拖出来,用统一的接口来包装。这个接口可以包含一个 C++类所能包含的任何东西,如内嵌类型、成员函数、成员变量。作为客户的模板代码,可以通过 traits 模板类所公开的接口来间接访问。
基本步骤
- 定义基本模板类
- 模板特化
- 统一模板调用类的编制
步骤 | 思想 | 目标 |
---|---|---|
定义基本模板类、模板特化 | 显式模板特殊化 | 类型差异 |
统一模板调用类的编制 | 用统一的接口来包装 | 统一处理 |
总结
统一模板调用类的存在,是为了统一处理复合类型,对于共性的使用,是基于具体的对象而调用的,而对于返回类型的控制,则是由具体的复合类型所确定的,而具体的复合类型与统一模板调用类的组合也是一种组合类型
需要注意的是,复合类型指的是程序员自己定义的类型。除此之外,在一个类型下有多个对象显然是理所应当的
从某一角度来看,共性指的是对不同复合类型(类)的相同操作(这些操作由于类型的不同而各不相同)
本质上,还是一个具体的对象调用一个具体的方法,但通过统一模板调用类来控制有必要存在的类型变化,从而使其能够统一调用某个函数的同时,而不需要担心类型相关的问题
综上所述,处理不同复合类型中类型相关的问题是萃取的必要条件,而通过统一的接口来调用它们共性的方法则是萃取的根本目的
操作符重载
#include <iostream>
using namespace std;
// 模板与运算符重载
// 知识回顾:
// 强制类型转换
// float a = 3.4
// const int & b = a(c); a ---> 3(c) //强制类型转换
// int a = 80;
// const Stu & s1 = a; a ---> ("", 80)s // 利用构造函数,Stu s(80);
// 运算符重载
// 1. 成员函数 - 对象调用
// 2. 友元函数 - 均作为参数,无需调用
// 3. 全局函数
class Stu {
string name;
int score;
public:
Stu(int b = 0, string a = "") // 强制类型转换,注意调换顺序 - 例如:Stu s(80);
{
name = a;
score = b;
}
Stu(string a = "", int b = 0) // 重载构造函数,亦可调换对象声明的参数顺序
{
name = a;
score = b;
}
/*
bool operator>(int value)
{
return this->score > value; // 写作 score > value 亦可
}
*/
bool operator>(const Stu & another) // const 引用,提高代码重用性;保证数据真实性;节省空间
{
return this->score > another.score;
}
};
template<typename T, typename G>
bool MyGreater(T a, G b)
{
return a > b;
}
int main()
{
// 模板与运算符重载
cout << MyGreater(3, 4) << endl;
cout << MyGreater(3, 5.6) << endl;
cout << MyGreater(30, 'y') << endl;
// s1 是否考过 80分?---> s1 > 80 而非 s1.score > 80(非专业人员)
Stu s1("Reyn", 100);
cout << MyGreater(s1, 80) << endl; // s1.operator > (80)
Stu s2("Lisa", 95);
cout << MyGreater(s1, s2) << endl;
return 0;
}
在下一篇文章,我们将介绍 C++ 中的输入输出(I / O)流
边栏推荐
- UI automation tool of CSDN salary increase technology: uiautomator2
- Qt QTextEdit 设置 QScrollBar 样式表不生效解决方案
- 一条 SQL 的执行过程
- One article solution! A40i three most common network card software problems
- HLS介绍
- volatile详解
- 7月上热搜50次!周杰伦新专辑1天1.5亿!歌手新歌爆红的营销路径
- 06. FFmpeg之libavdevice库
- 气泡水位计的工作原理及注意事项
- OPPO回应其折叠屏手机酷似华为Mate X:自研非公模!
猜你喜欢
Compose中的“ViewPager“和Banner
ITMS介绍
ES6中的箭头函数
PHP仓库进销存管理系统源码 WMS源码
Super long distance networking scheme of fire engine in offshore wind power fire alarm system
搭建关键字驱动自动化测试框架
Let, const declaration format and characteristics
关于君正T41、T40、T31版本的选择参考都在这里
The difference between router and switch
Source insight tips
随机推荐
展锐首款5G基带芯片正式发布,成功跻身5G第一梯队!
R语言检验组的等比例:使用prop.test函数检验两个组的成功的比例是否相等
ES6中的模板字符串,简化对象写法
Analyze RTP flow packet loss and disorder
ARM PWN基础教程
移动端测试必备技能: adb命令和抓包
展锐市场副总裁周晨专访:回应了关于5G芯片春藤510的一切!
Masonry小技巧之UIScrollView自适应
06. FFmpeg之libavdevice库
uniapp自定义应用退出执行内容
ES6中的箭头函数
一文解决! A40i最常见的3种网卡软件问题
日语动词+动词类型+动词活用
What is the reason why the easycvr video Plaza device list cannot be scrolled and loaded?
Step by step towards responsive programming (III) - common functional interfaces - function < T, R>
Compose中的“ViewPager“和Banner
安世半导体管理层拜会闻泰科技和格力电器
TR069事件类型(EVENT CODE对应的含义)
外表简单内里复杂的功能测试,如何进行?
G1垃圾回收器