还在因为写项目函数太多而烦恼?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

相关文章
WK
|
16天前
|
机器学习/深度学习 人工智能 算法
那C++适合开发哪些项目
C++ 是一种功能强大、应用广泛的编程语言,适合开发多种类型的项目。它在游戏开发、操作系统、嵌入式系统、科学计算、金融、图形图像处理、数据库管理、网络通信、人工智能、虚拟现实、航空航天等领域都有广泛应用。C++ 以其高性能、内存管理和跨平台兼容性等优势,成为众多开发者的选择。
WK
37 1
|
26天前
|
程序员 C++ 容器
在 C++中,realloc 函数返回 NULL 时,需要手动释放原来的内存吗?
在 C++ 中,当 realloc 函数返回 NULL 时,表示内存重新分配失败,但原内存块仍然有效,因此需要手动释放原来的内存,以避免内存泄漏。
|
29天前
|
编译器 程序员 C++
【C++打怪之路Lv7】-- 模板初阶
【C++打怪之路Lv7】-- 模板初阶
16 1
|
1月前
|
Ubuntu Linux 编译器
Linux/Ubuntu下使用VS Code配置C/C++项目环境调用OpenCV
通过以上步骤,您已经成功在Ubuntu系统下的VS Code中配置了C/C++项目环境,并能够调用OpenCV库进行开发。请确保每一步都按照您的系统实际情况进行适当调整。
261 3
|
1月前
|
存储 前端开发 C++
C++ 多线程之带返回值的线程处理函数
这篇文章介绍了在C++中使用`async`函数、`packaged_task`和`promise`三种方法来创建带返回值的线程处理函数。
45 6
|
1月前
|
C++
C++ 多线程之线程管理函数
这篇文章介绍了C++中多线程编程的几个关键函数,包括获取线程ID的`get_id()`,延时函数`sleep_for()`,线程让步函数`yield()`,以及阻塞线程直到指定时间的`sleep_until()`。
23 0
C++ 多线程之线程管理函数
|
1月前
|
编译器 C语言 C++
C++入门3——类与对象2-2(类的6个默认成员函数)
C++入门3——类与对象2-2(类的6个默认成员函数)
23 3
|
1月前
|
编译器 C语言 C++
详解C/C++动态内存函数(malloc、free、calloc、realloc)
详解C/C++动态内存函数(malloc、free、calloc、realloc)
154 1
|
1月前
|
存储 编译器 C++
C++入门3——类与对象2-1(类的6个默认成员函数)
C++入门3——类与对象2-1(类的6个默认成员函数)
30 1
|
1月前
|
编译器 C语言 C++
C++入门6——模板(泛型编程、函数模板、类模板)
C++入门6——模板(泛型编程、函数模板、类模板)
41 0
C++入门6——模板(泛型编程、函数模板、类模板)