您的位置:首页 > 编程语言 > C语言/C++

C++ 模板使用

2014-11-17 08:16 169 查看
模板是解决重用的一种方式,"模板" 顾名思义,一个框框,框架不会轻易变动,但其中的内容可以随意填写。

以一个栈的定义为例:

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: