还在因为写项目函数太多而烦恼?C++模板一文带你解决难题

简介: 还在因为写项目函数太多而烦恼?C++模板一文带你解决难题

💝一、什么是模板

模板是一种忽略数据的一种泛型编程。把数据当做未知量,当使用的时候传入类型的一种编程方式


语法


template <class T>//告诉编译器,接下来要用到一个未知类型是T类型

template <typename T>//等效class

template <class T1,class T2,class T3> //三个未知类型

#include<iostream>

#include<string>

using namespace std;

#if 0

int Max(int a, int b)

{

return a > b ? a : b;

}

float Max(float a, float b)

{

return a > b ? a : b;

}

double Max(double a, double b)

{

return a > b ? a : b;

}

#endif

template <class T1> T1 Max(T1 a,T1 b)

{

return a > b ? a : b;

}

int main()

{

cout << Max<int>(9, 10);

return 0;

}


二、C++函数模板

函数模板调用

函数模板隐式调用

显示调用:函数名<未知类型>(函数参数)

函数模板本质就是函数传参

函数模板也是可以缺省

函数模板中存在变量

这种函数模板必须显示调用

变量传参只能传入常量

当函数模板和普通函数相遇

优先调用类型一致的普通函数

显示调用一定调用模板

函数模板重载

优先调用传参数目少的函数模板

#include<iostream>

#include<string>

using namespace std;

template <class T1> T1 Max(T1 a, T1 b)

{

return a > b ? a : b;

}

template <class _T1, class _T2, class _T3> void print(_T1 a, _T2 b, _T3 c)

{

cout << a << "\t" << b << "\t" << c << endl;

}

template <class _T1 = int, class _T2 = string, class _T3 = double> void printData(_T1 a, _T2 b, _T3 c)

{

cout << a << endl << b << endl << c << endl;

}

template <class _T1,int size> _T1* createNew()

{

_T1* createNew = new _T1[size];

return createNew;

}

template <class _T1, int size=5> _T1* createParry()

{

_T1* createNew = new _T1[size];

return createNew;

}

template <class _Ty, int size = 4> void printArray2(_Ty array[])

{

for (int i = 0; i < size; i++)

{

 cout << array[i] << "\t";

}

cout << endl;

}

void Func1(int a, double b, string c)

{

cout << "普通函数" << endl;

}

template <class _T1, class _T2, class _T3> void Func1(_T1 a,_T2 b,_T3 c) { cout << "三个" << endl; }

template <class _T1, class _T2> void Func1(_T1 a, _T2 b, _T2 c) { cout << "两个" << endl; }

template <class _T1> void Func1(_T1 a,_T1 b,_T1 c) { cout << "一个" << endl; }


void test1()

{

//函数模板存在变量,必须显示调用

int* parry = createNew<int, 5>();

//变量缺省时候可以隐式调用

double* king = createParry<double>();

int p[4] = { 1,2,3,4 };

printArray2(p);

}

void test2()

{

//函数模板重载,普通函数

Func1<int, double, string>(1,1.11,string("king"));

Func1(1, 1.11,string("king"));

Func1(1, string("asdd"),string("kkk"));

Func1(1, 1, 1);

}

int main()

{

//隐式调用

cout << Max(1, 2) << endl;

cout << Max(1.1, 1.2) << endl;

cout << Max(string("abc"), string("abd")) << endl;

print(123, string("king"), 1.55);


//显示调用

cout << Max<int>(1, 2) << endl;

cout << Max<string>(string("abc"), string("abd")) << endl;

print<string, int, double>("asdas", 123, 123.213);


//函数模板的缺省

printData(1, "dad", 1.11);

printData<double, int, string>(1.11, 1, "dasdf");


test1();

test2();

return 0;

}

三、函数模板操作自定义类型

操作自定义类型的关键点就是重载

#include<iostream>

#include<string>

using namespace std;

template <class _T1> void printpArry(_T1 arry[],int arryNums)

{

for (int i = 0; i < arryNums; i++)

{

 cout << arry[i] << endl;

}

cout << endl;

}

template <class _T1> void Sort(_T1 arry[], int arryNums)

{

for (int i = 0; i < arryNums; i++)

{

 for (int j = 0; j < arryNums - i - 1; j++)

 {

  if (arry[j] > arry[j + 1])

  {

   _T1 temp = arry[j];

   arry[j] = arry[j + 1];

   arry[j + 1] = temp;

  }

 }

}

}

class MM

{

public:

MM(string name="", int age=0):name(name),age(age){}

friend ostream& operator<<(ostream& out,const MM& object)

{

 out << object.age << "\t" << object.name << endl;

 return out;

}

bool operator>(const MM& object)

{

 return this->name > object.name;

}

string Getname() const { return this->name; }

int Getage() const { return this->age; }

protected:

string name;

int age;

};

template <class _T1> void Sort2(_T1 arry[], int arryNums,bool(*compare)(const _T1& one,const _T1& two))

{

for (int i = 0; i < arryNums; i++)

{

 for (int j = 0; j < arryNums - i - 1; j++)

 {

  if (compare(arry[j] , arry[j + 1]))

  {

   _T1 temp = arry[j];

   arry[j] = arry[j + 1];

   arry[j + 1] = temp;

  }

 }

}

}

bool compareByname(const MM& one, const MM& two)

{

return one.Getname() > two.Getname();

}

bool compareByage(const MM& one, const MM& two)

{

return one.Getage() > two.Getage();

}

int main()

{

int parry[5] = { 1,20,6,7,90 };

Sort(parry, 5);

printpArry(parry, 5);

MM mm[3];

mm[0] = { "e",123 };

mm[1] = { "b",241 };

mm[2] = { "d",345 };

Sort(mm, 3);

printpArry(mm, 3);

Sort2(mm, 3,compareByage);

printpArry(mm, 3);

return 0;

}

💞四、C++类模板

template修饰的类就是类模板

模板类必须显示实例化,简单来说必须要传参

模板类不是一个真正的类型

声明和实现必须写在一起,所谓一起就是同一个文件中

所有用到类型的地方必须要用类名<未知类型>的用法

类模板特化

局部特化:特殊化处理,例如两个未知变成一个未知类型

完全特化:具体化类型

#include<iostream>

#include<string>

using namespace std;

template <class _T1,class _T2> class Data

{

public:

void print();

static int count;

};

template <class _T1, class _T2> int Data<_T1, _T2>::count = 0;

template <class _T1, class _T2> void Data<_T1, _T2>::print()

{

cout << "类中模板函数" << endl;

}

//类模板的继承

template <class _T1, class _T2> class Son : public Data<_T1, _T2>

{

public:

protected:

};

struct MMinfor

{

string name;

int age;

};

ostream& operator<<(ostream& out, const MMinfor& object)

{

out << object.age << "\t" << object.name << endl;

return out;

}

struct MMscore

{

int math;

int english;

int chinese;

};

ostream& operator<<(ostream& out, const MMscore& object)

{

out << object.math << "\t" << object.english << "\t" << object.chinese << endl;

return out;

}

template <class _T1, class _T2> class MM

{

public:

MM(_T1 one,_T2 two):one(one),two(two){}

void print() { cout << one << "\t" << two << endl; }

protected:

_T1 one;

_T2 two;

};

void test1()

{

MM < string, int > mm("king", 19);

mm.print();

MM<int, int> complaxe(1, 1);

complaxe.print();

//MMinfor info{string("zhang"), 18};

//MMscore score{ 13,14,123 };

//MM<MMinfor, MMscore> king(info, score);

MM<MMinfor, MMscore> king({ "zhang",18 }, { 31,312,453 });

king.print();

}

//类模板特化

template <class _T1, class _T2, class _T3> class A

{

public:

A(_T1 one,_T2 two,_T3 three):one(one),two(two),three(three)

{

 cout << "三个类型" << endl;

}

protected:

_T1 one;

_T2 two;

_T3 three;

};

//局部特化

template <class _T1> class A<_T1,_T1,_T1>

{

public:

A(_T1 one, _T1 two, _T1 three) :one(one), two(two), three(three)

{

 cout << "局部特化" << endl;

}

protected:

_T1 one;

_T1 two;

_T1 three;

};

//完全特化

template <> class A<int,int,int>

{

public:

A(int one, int two, int three) :one(one), two(two), three(three)

{

 cout << "完全特化" << endl;

}

protected:

int one;

int two;

int three;

};

void Test()

{

A<int, int, int> a(1, 2, 3);

A<int, string, double> b(1, "as", 1.22);

A<int, int, double> c(1, 2, 1.22);//三个类型

A<string, string, string> d("qew", "fasd", "fads");

}

int main()

{

Data<int, string> data;

Data<string, int>* object = new Data<string, int>;

data.print();

object->print();

//两个不同类型中的count,不会因为一个类型中值的改变而另一个类型中的值改变

cout << Data<int, string>::count << endl;

cout << Data<string, string>::count << endl;

test1();

Test();

return 0;

五、稍微复杂一点的类模板

稍微复杂一点的模板就是模板类与模板类的嵌套,本质不难,大家学会剥洋葱,学会用别名替换即可

#include<iostream>

#include<string>

using namespace std;

template <class _T1, class _T2> class MM

{

public:

MM(_T1 one, _T2 two) :one(one), two(two) {}

void print() { cout << one << "\t" << two << endl; }

template <class _T1, class _T2> friend ostream& operator<<(ostream& out,const MM<_T1, _T2>& object);

protected:

_T1 one;

_T2 two;

};

template <class _T1, class _T2> ostream& operator<<(ostream& out,const MM<_T1, _T2>& object)

{

out << object.one << "\t" << object.two << endl;

return out;

}

template <class _T1, class _T2> class Data

{

public:

Data(_T1 one,_T2 two):one(one),two(two){}

void print() { cout << one << "\t" << two << endl; }

template <class _T1, class _T2>friend ostream& operator<<(ostream& out, const Data<_T1, _T2>& object);

protected:

_T1 one;

_T2 two;

};

template <class _T1, class _T2> ostream& operator<<(ostream& out, const Data<_T1, _T2>& object)

{

out << object.one << "\t" << object.two << endl;

return out;

}

int main()

{

MM<int, string> info(19, "king");

MM<int, int> score(99, 88);

Data< MM<int, string>, MM<int, int>> king(info, score);

king.print();

using kk = Data< MM<int, string>, MM<int, int>>;

using kkk = MM<int, string>;

Data<kk, kkk> data(king, info);

data.print();

return 0;

}


版权声明:本文为CSDN博主「热爱编程的小K」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/qq_72157449/article/details/130047318

相关文章
|
19天前
|
存储 C++ 容器
C++STL(标准模板库)处理学习应用案例
【4月更文挑战第8天】使用C++ STL,通过`std:vector`存储整数数组 `{5, 3, 1, 4, 2}`,然后利用`std::sort`进行排序,输出排序后序列:`std:vector<int> numbers; numbers = {5, 3, 1, 4, 2}; std:sort(numbers.begin(), numbers.end()); for (int number : numbers) { std::cout << number << " "; }`
19 2
|
30天前
|
编译器 C++
C++入门指南:10分钟带你快速了解模板究竟是什么(建议收藏!!)
C++入门指南:10分钟带你快速了解模板究竟是什么(建议收藏!!)
33 0
|
16天前
|
存储 算法 Linux
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
40 6
|
15天前
|
编译器 C语言 C++
【C++初阶(九)】C++模版(初阶)----函数模版与类模版
【C++初阶(九)】C++模版(初阶)----函数模版与类模版
19 0
|
19天前
|
程序员 C++
C++语言模板学习应用案例
C++模板实现通用代码,以适应多种数据类型。示例展示了一个计算两数之和的模板函数`add&lt;T&gt;`,可处理整数和浮点数。在`main`函数中,展示了对`add`模板的调用,分别计算整数和浮点数的和,输出结果。
12 2
|
25天前
C/C++test两步完成CMake项目静态分析
通过将C/C++test集成到CMake项目中,并根据项目的需要进行配置,可以在两步内完成CMake项目的静态分析。这样可以帮助开发人员及时发现并修复潜在的代码问题,提高代码质量和可靠性。
8 0
|
26天前
|
存储 缓存 C++
C++链表常用的函数编写(增查删改)内附完整程序
C++链表常用的函数编写(增查删改)内附完整程序
|
28天前
|
存储 安全 编译器
【C++】类的六大默认成员函数及其特性(万字详解)
【C++】类的六大默认成员函数及其特性(万字详解)
35 3
|
1月前
|
安全 程序员 C++
【C++ 基本知识】现代C++内存管理:探究std::make_系列函数的力量
【C++ 基本知识】现代C++内存管理:探究std::make_系列函数的力量
101 0
|
1月前
|
设计模式 安全 C++
【C++ const 函数 的使用】C++ 中 const 成员函数与线程安全性:原理、案例与最佳实践
【C++ const 函数 的使用】C++ 中 const 成员函数与线程安全性:原理、案例与最佳实践
71 2