模板
模板就是建立通用的模具,大大提高复用性
模板的特点:
- 模板不可以直接使用,它只是一个框架
- 模板的通用并不是万能的
函数模板
-
C++另一种编程思想称为
泛型编程
,主要利用的技术就是模板 -
C++提供两种模板机制:函数模板和类模板
函数模板语法
函数模板作用:
建立一个通用函数,其函数返回值类型和形参类型可以不具体制定,用一个虚拟的类型来代表。
template<typename T>
函数声明或定义
解释:
template — 声明创建模板
-
typename — 表面其后面的符号是一种数据类型,可以用class代替
-
T — 通用的数据类型,名称可以替换,通常为大写字母
#include <iostream>
using namespace std;
// 交换整型函数
void swapInt(int& a, int& b){
int temp = a;
a = b;
b = temp;
}
// 交换浮点型函数
void swapDoublet(double & a, double& b){
double temp = a;
a = b;
b = temp;
}
template<typename T>
void mySwap(T& a, T& b){
T temp = a;
a = b;
b = temp;
}
int main() {
int a = 20;
int b = 50;
// 1.自动类型推导
mySwap(a, b);
// 2.显示类型推导
mySwap<int>(a,b);
cout <<"a = "<< a<<endl;
cout <<"b = "<< b<<endl;
}
- 函数模板利用关键字 template
- 使用函数模板有两种方式:自动类型推导、显示指定类型
- 模板的目的是为了提高复用性,将类型参数化
函数模板案例
- 利用函数模板封装一个排序的函数,可以对不同数据类型数组进行排序
- 排序规则从大到小,排序算法为
选择排序
- 分别利用char数组和int数组进行测试
#include <iostream>
using namespace std;
template<typename T>
void mySwap(T& a, T& b){
T temp = a;
a = b;
b = temp;
}
// 选择排序
template<typename T>
void selectSort(T arr[], int len){
for (int i = 0; i < len; i++) {
int max=i;
for (int j = i+1; j < len; j++) {
if (arr[max] < arr[j])
max = j;
}
if (max!=i)
mySwap(arr[max], arr[i]);
}
}
template<typename T>
void printArray(T arr[], int len){
cout<< "[";
for (int i = 0; i < len; i++) {
if (i==len-1)
cout<<arr[i] << "]" <<endl;
else
cout<< arr[i] << ",";
}
}
void test01(){
// char 数组
char charArr[] = "bdafciut";
int len = sizeof(charArr)/sizeof (charArr[0]);
selectSort<char>(charArr, len-1);
printArray<char>(charArr, len-1);
};
void test02(){
// int 数组
int arr[] = {22, 344, 566, 3, 44, 5};
int len = sizeof(arr)/sizeof (arr[0]);
selectSort<int>(arr, len);
printArray<int>(arr, len);
};
int main (){
// test01();
test02();
return 0;
}
类模板语法
类模板作用:
- 建立一个通用类,类中的成员 数据类型可以不具体制定,用一个虚拟的类型来代表。
template<typename T>
函数声明或定义
解释:
template — 声明创建模板
-
typename — 表面其后面的符号是一种数据类型,可以用class代替
-
T — 通用的数据类型,名称可以替换,通常为大写字母
#include <iostream>
using namespace std;
template<class NameType, class AgeType>
class Person{
public:
NameType name;
AgeType age;
public:
Person(NameType name, AgeType age){
this->name = name;
this->age = age;
}
void showPerson(){
cout<< "name = "<< this->name<< ", age = "<< this->age <<endl;
}
};
int main (){
// 使用时必须确定类型
Person<string, int> p1("eric", 12);
p1.showPerson();
return 0;
}
运算符重载
运算符重载概念:对已有的运算符重新进行定义,赋予其另一种功能,以适应不同的数据类型
加号运算符重载
作用:实现两个自定义数据类型相加的运算
#include <iostream>
using namespace std;
class Vector{
public:
int *data;
int size;
public:
Vector(){
}
Vector(int *arr, int len){
data = arr;
size = len;
}
Vector & operator+(const Vector& v){
//定义重载 + 号的规则
for (int i = 0; i < size; i++) {
(*this).data[i] = this->data[i] + v.data[i];
}
return *this;
}
void show(){
cout<< "[";
for (int i = 0; i < size; i++) {
if (i==size-1)
cout<<data[i] << "]" <<endl;
else
cout<< data[i] << ",";
}
}
};
int main (){
const int n = 3;
int arr1[n] = {1, 2, 3}; // ls = [1, 2, 3]
int arr2[n] = {2, 3, 4};
Vector v1(arr1, n); // np.array(ls)
Vector v2(arr2, n); // v1 + v2 = [3, 5, 7]
v1.show();
v2.show();
Vector v3;
v3 = v1 + v2;
v3.show();
return 0;
}
//
// Created by Eric Li on 2022/3/3.
//
#ifndef JINLOU_STUDENT_H
#define JINLOU_STUDENT_H
#include <iostream>
#include <string>
using namespace std;
struct Student{
string name;
int score;
bool operator<(const Student& otherStudent){
return score != otherStudent.score ?
score > otherStudent.score : name < otherStudent.name;
}
friend ostream& operator<<(ostream &os, const Student &student){
os<< "Student: "<< student.name << " " << student.score << endl;
return os;
}
};
#endif //JINLOU_STUDENT_H
#include <iostream>
#include "Student.h"
using namespace std;
template<typename T>
void selectionSort(T arr[], int len){
for (int i = 0; i < len; i++) {
int minIndex=i;
for (int j = i+1; j < len; j++) {
if (arr[j] < arr[minIndex] )
minIndex = j;
}
swap(arr[i], arr[minIndex]);
}
}
int main (){
// 测试模板函数,传入整型数组
int a[10] = {10,9,8,7,6,5,4,3,2,1};
selectionSort( a , 10 );
for( int i = 0 ; i < 10 ; i ++ )
cout<<a[i]<<" ";
cout<<endl;
// 测试模板函数,传入浮点数数组
float b[4] = {4.4,3.3,2.2,1.1};
selectionSort(b,4);
for( int i = 0 ; i < 4 ; i ++ )
cout<<b[i]<<" ";
cout<<endl;
// 测试模板函数,传入字符串数组
string c[4] = {"D","C","B","A"};
selectionSort(c,4);
for( int i = 0 ; i < 4 ; i ++ )
cout<<c[i]<<" ";
cout<<endl;
Student d[4] = {{"D", 80},{"B", 30},{"A", 100},{"C", 80},};
selectionSort(d, 4);
for (int i = 0; i < 4; i++)
cout << d[i];
cout<<endl;
return 0;
}
SortTestHelper.h
//
// Created by Eric Li on 2022/3/3.
//
#ifndef JINLOU_SORTTESTHELPER_H
#define JINLOU_SORTTESTHELPER_H
#include <iostream>
#include <ctime>
#include <cassert>
using namespace std;
namespace SortTestHelper{
// 生成有n个元素的随机数组,每个元素的随机范围为[rangeL, rangeR]
int * generateRandomArray(int n, int rangeL, int rangeR){
assert(rangeL<=rangeR);
int *arr = new int[n];
srand(time(NULL));
for (int i = 0; i < n; i++) {
arr[i] = rand()%(rangeR-rangeL+1) + rangeL;
}
return arr;
}
// 打印
template<typename T>
void printArray(T arr[], int n){
for (int i = 0; i < n; i++)
cout << arr[i]<<" ";
cout<<endl;
return;
}
//
}
#endif //JINLOU_SORTTESTHELPER_H
测试辅助函数
#include <iostream>
using namespace std;
#include "SortTestHelper.h"
template<typename T>
void selectionSort(T arr[], int len){
for (int i = 0; i < len; i++) {
int minIndex=i;
for (int j = i+1; j < len; j++) {
if (arr[j] < arr[minIndex] )
minIndex = j;
}
swap(arr[i], arr[minIndex]);
}
}
int main (){
int N = 20000;
int *arr = SortTestHelper::generateRandomArray(N, 0 , 100000);
selectionSort(arr, N);
SortTestHelper::printArray(arr, N);
delete[] arr;
return 0;
}