模板类的使用注意事项
2016-07-06 20:45
627 查看
组织模板代码有三种方式
1.包含模型(常规写法 将实现写在头文件中)
2.显式实例化(实现写在cpp文件中,使用template class语法进行显式实例化)
3.分离模型(使用C++ export关键字声明导出)
第三种方式理论最优,但是实际从C++标准提出之后主流编译器没有支持过,并且在最新的C++11标准中已经废除此特性,export关键字保留待用。
头文件定义:
实现:
测试:
编译出错:
![](http://img.blog.csdn.net/20160706204737027?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
C++中每一个对象所占用的空间大小,是在编译的时候就确定的,在模板类没有真正的被使用之前,编译器是无法知道,模板类中使用模板类型的对象的所占用的空间的大小的。只有模板被真正使用的时候,编译器才知道,模板套用的是什么类型,应该分配多少空间。这也就是模板类为什么只是称之为模板,而不是泛型的缘故。
所以模板类的实现,脱离具体的使用,是无法单独的编译的;把声明和实现分开的做法也是不可取的,必须把实现全部写在头文件里面。
将模板类的定义和实现放到一起JStack.h中即可。
1.包含模型(常规写法 将实现写在头文件中)
2.显式实例化(实现写在cpp文件中,使用template class语法进行显式实例化)
3.分离模型(使用C++ export关键字声明导出)
第三种方式理论最优,但是实际从C++标准提出之后主流编译器没有支持过,并且在最新的C++11标准中已经废除此特性,export关键字保留待用。
头文件定义:
#ifndef JSTACK_H #define JSTACK_H #include <iostream> #include <assert.h> using namespace std; void test(); template<class T> class JStack; template<class T> ostream& operator << (ostream& out,JStack<T>& s); template<class T> struct JNode{ T element; JNode<T>* next; JNode(T value,JNode<T>* p=NULL):element(value),next(p){} }; template<class T> class JStack { public: JStack(){head=NULL;}; void push(const T element); bool pop(T& element); bool getTop(T& element)const; bool isEmpty(); int getSize(); void allEarse(); friend ostream& operator << <>(ostream& out,JStack<T>& s); virtual ~JStack(); private: JNode<T>* head; }; #endif // JSTACK_H
实现:
#include "JStack.h" template<class T> void JStack<T>::push(const T element) { head=new JNode<T>(element,head); assert(NULL!=head); } template<class T> bool JStack<T>::pop(T& element) { if(this->isEmpty()) return false; element=head->element; JNode<T>* p=head->next; delete head; head=p; return true; } template<class T> bool JStack<T>::getTop(T& element)const { if(this->isEmpty()) return false; element=head->element; return true; } template<class T> bool JStack<T>::isEmpty() { if(NULL==head) return true; return false; } template<class T> int JStack<T>::getSize() { int counter=0; JNode<T>* p=head; while(NULL!=p) { counter++; p=p->next; } return counter; } template<class T> void JStack<T>::allEarse() { while(NULL!=head) { delete head; head=head->next; } } template<class T> ostream& operator<<(ostream& out,JStack<T>& s) { if(s.isEmpty()) return out; out<<"[stack size]"<<s.getSize()<<endl; JNode<T>* p=s.head; while(NULL!=p) { cout<<p->element<<"\t"; p=p->next; } cout<<endl; return out; } template<class T> JStack<T>::~JStack() { this->allEarse(); }
测试:
#include "JStack.h" using namespace std; int main() { test(); JStack<int> s; cout<<s.getSize()<<endl; s.push(1); s.push(100); s.push(200); cout<<s.getSize()<<endl; int tmp; s.pop(tmp); cout<<"[top]"<<tmp<<endl; cout<<s; return 0; }
编译出错:
C++中每一个对象所占用的空间大小,是在编译的时候就确定的,在模板类没有真正的被使用之前,编译器是无法知道,模板类中使用模板类型的对象的所占用的空间的大小的。只有模板被真正使用的时候,编译器才知道,模板套用的是什么类型,应该分配多少空间。这也就是模板类为什么只是称之为模板,而不是泛型的缘故。
所以模板类的实现,脱离具体的使用,是无法单独的编译的;把声明和实现分开的做法也是不可取的,必须把实现全部写在头文件里面。
将模板类的定义和实现放到一起JStack.h中即可。
#pragma once #include <iostream> #include <assert.h> using namespace std; template<class T> class JStack; template<class T> ostream& operator << (ostream& out, JStack<T>& s); template<class T> struct JNode{ T element; JNode<T>* next; JNode(T value, JNode<T>* p = NULL) :element(value), next(p){} }; template<class T> class JStack { public: JStack(){ head = NULL; }; void push(const T element); bool pop(T& element); bool getTop(T& element)const; bool isEmpty(); int getSize(); void allEarse(); friend ostream& operator << <>(ostream& out, JStack<T>& s); virtual ~JStack(); private: JNode<T>* head; }; template<class T> void JStack<T>::push(const T element) { head = new JNode<T>(element, head); assert(NULL != head); } template<class T> bool JStack<T>::pop(T& element) { if (this->isEmpty()) return false; element = head->element; JNode<T>* p = head->next; delete head; head = p; return true; } template<class T> bool JStack<T>::getTop(T& element)const { if (this->isEmpty()) return false; element = head->element; return true; } template<class T> bool JStack<T>::isEmpty() { if (NULL == head) return true; return false; } template<class T> int JStack<T>::getSize() { int counter = 0; JNode<T>* p = head; while (NULL != p) { counter++; p = p->next; } return counter; } template<class T> void JStack<T>::allEarse() { while (NULL != head) { delete head; head = head->next; } } template<class T> ostream& operator<<(ostream& out, JStack<T>& s) { if (s.isEmpty()) return out; out << "[stack size]" << s.getSize() << endl; JNode<T>* p = s.head; while (NULL != p) { cout << p->element << "\t"; p = p->next; } cout << endl; return out; } template<class T> JStack<T>::~JStack() { this->allEarse(); }
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C++联合体转换成C#结构的实现方法
- C++高级程序员成长之路
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法
- C++中调用Lua函数实例
- Lua和C++的通信流程代码实例
- C++的template模板中class与typename关键字的区别分析
- C与C++之间相互调用实例方法讲解