模板是解决重用的一种方式,"模板" 顾名思义,一个框框,框架不会轻易变动,但其中的内容可以随意填写。
以一个栈的定义为例:
class stack
{
private:
enum {ssize = 100};
int m_stack[ssize];
int m_top;
public:
stack() : m_top(0) {m_stack[m_top] = 0;}
void push(int i)
{ if (m_top < ssize) {m_stack[m_top++] = i;}; }
int pop()
{ return stack[m_top > 0 ? --m_top : m_top]; }
}
这个栈最多可以被叫做 int_stack,它只能支持int 类型, 但对与 double 或其他复合类型它就无法满足了。这里的代码也无法被重用。
这时候使用模板就可以很好的解决这个问题。
模板的定义和使用
模板的定义很简单, 使用关键字 template
template <class T>
class stack
{
private:
enum {ssize = 100};
T m_stack[ssize];
int m_top;
public:
stack() : m_top(0) {m_stack[m_top] = 0;}
void push(T i)
{ if (m_top < ssize) {m_stack[m_top++] = i;}; }
T pop()
{ return stack[m_top > 0 ? --m_top : m_top]; }
}
这个类中把int 改为了 T 类型, 这样stack的框框就确定下来了,但其中的内容是可以随意变化的。可以使用double 当然也可以使用复合类型或者是类。
使用 模板类, 模板类被很好的重用了。
#include "stack_t.h"
void main()
{
stack<int> istack;
stack<double> dstack;
int i = 0;
double d = 0;
for (i = 0; i < 10; i++)
{
istack.push(i*i);
}
for (i = 0; i < 10; i++)
{
d = i * 0.01;
dstack.push(d);
}
for (i = 0; i < 10; i++)
{
cout << istack.pop() << " ";
}
cout << endl << endl;
for (i = 0; i < 10; i++)
{
cout << dstack.pop() << " ";
}
cout << endl;
cin >> i;
}
当然模板类中也可以不使用内联函数, 但模板类的声明和实现一定要放在一起,都放在头文件中,否则连接时会出现错误。原因是 由template <...> 处理的任何东西都意味着编译器在当时不为它分配存储空间,它一直处于等待状态直到被一个模板实例告知.
#include <iostream>
using namespace std;
#ifndef _STACK_H_
#define _STACK_H_
template <class T>
class stack
{
private:
enum {ssize = 100};
T m_stack[ssize];
int m_top;
public:
stack() : m_top(0) {m_stack[m_top] = 0;}
void push(T t);
T pop();
};
template <class T>
void stack<T>::push(T t)
{
if (m_top < ssize) {m_stack[m_top++] = t;};
}
template <class T>
T stack<T>::pop()
{
return m_stack[m_top > 0 ? --m_top : m_top];
}
#endif
使用模板时内存的释放
一个小小的例子,这个例子可以直接复制到程序中,来节省开发的时间。从例子中也可以看出, 模板类,或者是容器类他们对于对象类型并不负责内存的释放。
内存的释放还是由运行类自己进行的。
#include <iostream>
#include <vector>
using namespace std;
class Tester
{
private:
int m_id;
public:
Tester(int id): m_id(id){cout << "Construct a Tester: << "<< m_id << endl;}
~Tester(){cout << "Destruct a Tester: "<< m_id << endl;}
void run() {cout << "I am Tester: "<< m_id << endl;};
};
void main()
{
vector<Tester*> vec;
int i = 0;
vec.push_back(new Tester(1));
vec.push_back(new Tester(2));
vec.push_back(new Tester(3));
vec.push_back(new Tester(4));
vec.push_back(new Tester(5));
for (vector<Tester*>::iterator it = vec.begin(); it != vec.end(); it ++)
if (NULL != *it)
{
(*it)->run();
}
for (vector<Tester *>::iterator it = vec.begin(); it != vec.end(); it ++)
if (NULL != *it)
{
delete *it;
*it = NULL;
}
vec.clear();
cin >> i;
}
模板的继承:
模板类与我们普通的类一样支持继承。这里保留一个小例子,以后开发过程中可以直接扩展使用。这里使用的基类就是上面的栈的例子,这里从基类中派生出一个简单的子类,子类中增加了一个统计个数的功能。
stack_t.h
#include <iostream>
using namespace std;
#ifndef _STACK_H_
#define _STACK_H_
template <class T>
class stack
{
protected:
enum {ssize = 100};
T m_stack[ssize];
int m_top;
public:
stack() : m_top(0) {m_stack[m_top] = 0;}
void push(T t);
T pop();
};
template <class T>
void stack<T>::push(T t)
{
if (m_top < ssize) {m_stack[m_top++] = t;};
}
template <class T>
T stack<T>::pop()
{
return m_stack[m_top > 0 ? --m_top : m_top];
}
#endif
stack_static.h
#include <iostream>
#include "stack_t.h"
using namespace std;
#ifndef _STACK_STATIC_H_
#define _STACK_STATIC_H_
template <class T>
class stack_static : public stack<T>
{
public:
stack_static(){};
int count(){return m_top;};
};
#endif
main.cpp
#include "stack_static.h"
void main()
{
stack_static<int> istack;
stack_static<double> dstack;
int i = 0;
double d = 0;
for (i = 0; i < 10; i++)
{
istack.push(i*i);
}
for (i = 0; i < 10; i++)
{
d = i * 0.01;
dstack.push(d);
}
cout << "===================================" << endl;
cout << "Total count: " << dstack.count() << endl;
cout << "===================================" << endl;
for (i = 0; i < 10; i++)
{
cout << istack.pop() << " ";
}
cout << endl << endl;
for (i = 0; i < 10; i++)
{
cout << dstack.pop() << " ";
}
cout << endl;
cin >> i;
}