C++之函数模板、类模板、模板的特化
创始人
2024-01-21 10:32:16
0

1.什么是模板?

模板是c++的一种特性,允许函数或者类(对象)通过泛型(generic types)的形式表现或者运行模板可以使得函数或类在对应不同的类型(types)的时候正常工作,而无需为每一种类型分别写一份代码。

为了代码重用,代码就必须是通用的;通用的代码就必须不受数据类型的限制。那么我们可以把数 据类型改为一个设计参数。这种类型的程序设计称为参数化(parameterize) 程序设计。软件模块由模板 (template) 构造。 包括函数模板(function template)和类模板(class template)。

2.类模板的定义如下:


template<类型模板参数表>
class 类名
{…… //类声明体
}; //再次指出分号不可少
template<类型模板参数表>
返回类型 类名<模板参数表>::成员函数名1(形参表)
{……;//成员函数定义体
}
……
template<类型模板参数表>
返回类型 类名<模板参数表>::成员函数名n(形参表)
{……;//成员函数n定义体
}
//类型替换的过程被称为模板实例化 template instantiation
1

3.模板分类?

1.模板参数有两种:

模板类型参数和模板非类型参数

2.模板的类型

1.函数模板

函数模板是参数化的一族函数(a famliy of functions)

通过函数模板,可以实例化一系类函数,这些函数都给予同一套模板框架,但是作用在不通类型的参数上

示例 :(针对不同的数据类型 比较两个数据的大小)

求最大值:int型、char型。double型等等

int Max(int a, int b)
{return a > b ? a : b;
}double Max(double a, double b)
{return a > b ? a : b;
}char Max(char a, char b)
{return a > b ? a : b;
}void main()
{cout << Max(5, 3) << endl;cout << Max(5.3, 7.3) << endl;cout << Max('C', 'c') << endl;
}

模板参数是由传递给模板函数的实参决定的

不允许自动类型转换:每个T必须严格匹配

 

使用模板

template             //函数模板--经过类型参数化--->模板函数
T Max(T a, T b)
{return a > b ? a : b;
}

 //模板的特化--具体化

template<>
const char* Max(const char* a, const char* b)
{cout << "const char* Max" << endl;return strcmp(a, b) > 0 ? a : b;
}

主函数

void main()
{cout << Max(4, 6) << endl;  //类型参数化 intcout << Max(3.4, 1.2) << endl; //doublecout << Max('a', '1') << endl; //charcout << Max("333", "555") << endl; //const char*
}

运行结果

 2.类模板

与函数模板类似,类也可以通过参数泛化,从而可以构建出一族不同的类实例(对象)

类模板实参可以是某一类型或常量(仅限int或enum)

类模板特化

允许对一个类模板的某些模板参数类型做特化

特化的作用和好处

对于某种特殊的类型,可能可以做些特别的优化或提供不同的实现

避免在实例化的时候引起一些可能不好的行为

特化一个类模板的时候也意味着需要特化其所有参数化的成员函数

template
class A
{
public:A(T i) :m_i(i) {}void print(){cout << "m_i = " << m_i << endl;}
private:T m_i;
};
//vector  list stack  queuetemplate<>
class A
{
public:A(const char* i){cout << "A const char*" << endl;m_i = new char[strlen(i) + 1];strcpy_s(m_i, strlen(i) + 1, i);}void print(){cout << "A::m_i = " << m_i << endl;}~A(){delete[]m_i;}
private:char* m_i;
};
void main()
{A a(4);  //将int当成参数传递给模板中的T--》模板类a.print();A b('6');b.print();A c(3.5);c.print();A d("helloworld");d.print();
}

 

4.模板实例化

模板的声明(declaration)其实并未给出一个函数或者类的完全定义(definition),只是提供了一个函数或者类的语法框架(syntactical skeleton)

实例化是指从模板构建出一个真正的函数或者类的过程。用具体类型代替模板参数的过程叫做实例化;从而产生一个模板实例。

如果实例化一种类型,而该类型并不支持函数所使用的操作,那么就会导致一个编译错误。

实例化有两种类型
1:显示实例化-在代码中明确指定要针对哪种类型进行实例化

2:隐式实例化-在首次使用时根据具体情况使用一种合适的类型进行实例化


#include 
bool great(char a, char b)
{return a > b;
}
class Great
{
public:bool operator()(char a, char b){return a > b;}
};
template
class GREAT
{
public:bool operator()(T a, T b){return a > b;}
};
void main()
{//int a[] = { 7,6,8,9,0,2,2,3,4,5,6,7 };char a[] = { '1','a','h','5','3','2','d','k','v','0','x' };int n = sizeof(a) / sizeof(a[0]);//sort(a, a + n); //将a到a+n从小到大进行排序---模板//sort(a, a + n, greater());  //用的库中的greater//sort(a, a + n, great);//sort(a, a + n, Great()); //调用Great类中的()重载sort(a, a + n, GREAT());for (int i = 0; i < n; i++)cout << a[i] << " ";cout << endl;
}

 5.模板实现链栈

1.C语言版


class MyStack
{
private:struct StackNode{int data;StackNode* next;public:StackNode(int val = 0, StackNode* p = nullptr):data(val), next(p) {}};
private:StackNode* top; // heap;int cursize;void clone(const MyStack& s){Clear();cursize = s.cursize;StackNode* p = s.top;if (p == nullptr) return;top = new StackNode(p->data); //StackNode* tail = top;p = p->next;while (p != nullptr){tail = tail->next = new StackNode(p->data);p = p->next;}}
public:MyStack() :top(nullptr), cursize(0) {}MyStack(const MyStack& s):top(nullptr), cursize(s.cursize){clone(s);} // MyStack yous(mys);MyStack& operator=(const MyStack& s){if (this != &s){clone(s);}return *this;} // mys = hes;// top;~MyStack(){Clear();}void Clear(){while (top != nullptr){StackNode* q = top;top = q->next;delete q;}cursize = 0;}int Size() const { return cursize; }bool Empty() const { return Size() == 0; }void Push(int val){top = new StackNode(val, top); // 1 2 heapcursize += 1;}int& Top() { return top->data; }const int& Top()const { return top->data; }void Pop(){StackNode* q = top;top = q->next;delete q;cursize -= 1;}bool GetTop(int& val){if (Empty()) return false;val = top->data;StackNode* q = top;top = q->next;delete q;cursize -= 1;return true;}
};
int main()
{MyStack mys;for (int i = 0; i < 10; ++i){mys.Push(i);}MyStack ys(mys);
}

2.C++版本                         


template //
class MyStack
{
public:struct StackNode{T data; // int data;StackNode* next;public:StackNode(const T& val = T(), StackNode* p = nullptr):data(val), next(p) {}};
private:StackNode* top; // heap;int cursize;void clone(const MyStack& s){Clear();cursize = s.cursize;StackNode* p = s.top;if (p == nullptr) return;top = new StackNode(p->data); //StackNode* tail = top;p = p->next;while (p != nullptr){tail = tail->next = new StackNode(p->data);p = p->next;}}
public:MyStack() :top(nullptr), cursize(0) {}MyStack(const MyStack& s):top(nullptr), cursize(s.cursize){clone(s);} // MyStack yous(mys);MyStack& operator=(const MyStack& s){if (this != &s){clone(s);}return *this;} // mys = hes;// top;~MyStack(){Clear();}void Clear(){while (top != nullptr){StackNode* q = top;top = q->next;delete q;}cursize = 0;}int Size() const { return cursize; }bool Empty() const { return Size() == 0; }void Push(const T& val) // T{top = new StackNode(val, top); // 1 2 heapcursize += 1;}T& Top() { return top->data; }const T& Top()const { return top->data; }void Pop(){StackNode* q = top;top = q->next;delete q;cursize -= 1;}bool GetTop(T& val);
};
template
bool MyStack::GetTop(T& val)
{if (Empty()) return false;val = top->data;StackNode* q = top;top = q->next;delete q;cursize -= 1;return true;
}
int main()
{MyStack imys;MyStack cmys;MyStack pmys;MyStack::StackNode x;for (int i = 0; i < 3; ++i){pmys.Push(Point(i, i + 10));}Point px;while (pmys.GetTop(px)){cout << px.PointX() << " : " << px.PointY() << endl;}
}

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...