目录
模板是c++的一种特性,允许函数或者类(对象)通过泛型(generic types)的形式表现或者运行模板可以使得函数或类在对应不同的类型(types)的时候正常工作,而无需为每一种类型分别写一份代码。
为了代码重用,代码就必须是通用的;通用的代码就必须不受数据类型的限制。那么我们可以把数 据类型改为一个设计参数。这种类型的程序设计称为参数化(parameterize) 程序设计。软件模块由模板 (template) 构造。 包括函数模板(function template)和类模板(class template)。
-
- template<类型模板参数表>
- class 类名
- {
- …… //类声明体
- }; //再次指出分号不可少
- template<类型模板参数表>
- 返回类型 类名<模板参数表>::成员函数名1(形参表)
- {
- ……;//成员函数定义体
- }
- ……
- template<类型模板参数表>
- 返回类型 类名<模板参数表>::成员函数名n(形参表)
- {
- ……;//成员函数n定义体
- }
- //类型替换的过程被称为模板实例化 template instantiation
- 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<class T> //函数模板--经过类型参数化--->模板函数
- 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; //类型参数化 int
- cout << Max(3.4, 1.2) << endl; //double
- cout << Max('a', '1') << endl; //char
- cout << Max("333", "555") << endl; //const char*
- }
运行结果
与函数模板类似,类也可以通过参数泛化,从而可以构建出一族不同的类实例(对象)
类模板实参可以是某一类型或常量(仅限int或enum)
类模板特化
允许对一个类模板的某些模板参数类型做特化
对于某种特殊的类型,可能可以做些特别的优化或提供不同的实现
避免在实例化的时候引起一些可能不好的行为
特化一个类模板的时候也意味着需要特化其所有参数化的成员函数
- template<class T>
- class A
- {
- public:
- A(T i) :m_i(i) {}
- void print()
- {
- cout << "m_i = " << m_i << endl;
- }
- private:
- T m_i;
- };
- //vector list stack queue
-
- template<>
- class A<const char*>
- {
- 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<int> a(4); //将int当成参数传递给模板中的T--》模板类
- a.print();
- A<char> b('6');
- b.print();
- A<double> c(3.5);
- c.print();
- A<const char*> d("helloworld");
- d.print();
- }
模板的声明(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 T>
- 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<char>());
- for (int i = 0; i < n; i++)
- cout << a[i] << " ";
- cout << endl;
- }
-
- 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 heap
- cursize += 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);
- }
-
- template<class T> //
- 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 heap
- cursize += 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<class T>
- 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<int> imys;
- MyStack<char> cmys;
- MyStack
pmys; - MyStack<int>::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;
- }
- }