找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 3414|回复: 0

【C++】C++模板实现的stack

[复制链接]

33

主题

1

回帖

561

积分

用户组: 大·技术宅

UID
580
精华
26
威望
28 点
宅币
341 个
贡献
0 次
宅之契约
0 份
在线时间
8 小时
注册时间
2014-12-8
发表于 2014-12-8 17:58:57 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
C++中使用了模板来减少方法相同但是类型不一样带来的函数重载以及大量复制代码的问题。
这里主要说说类模板

类模板的定义:
  1. template<typename Type>
  2. class Stacks
  3. {
  4. public:
  5.         Stacks(void);
  6.         Stacks(int nSize);
  7.         Stacks(Type Arr[],int nSize);
  8.         ~Stacks(void);
  9. public:
  10.         bool isEmpty();
  11.         bool isFull();
  12.         bool push(const Type &e);
  13.         Type pop();
  14.         Type getTop();
  15.         int  getLength();
  16.         void print();
  17. private:
  18.         int m_top;
  19.         int m_nLength;
  20.         Type *m_pArr;
  21.        
  22. };
复制代码

函数的实现:
函数实现既可以放在类定义体内,又可以放在类定义体外,但是不管放在体内还是体外都必须放在头文件中,这点和inline函数有点类似。
分离编译:
如果声明和定义分别放在h文件和cpp文件呢?
这个时候如果在其他程序中用到了模板类中的函数,那么就会出现
1.png
诸如此类的错误,错误原因说的很清楚,就是说没有找到相关的函数定义。那为什么模板类的非模板类在分离编译上这一点有区别呢?
我们知道分离编译是以编译单元为单位,所谓的编译单元就是cpp文件,编译器在进行编译的时候,会首先进行预编译(展开头文件),然后进行编译,将单独的编译单元生成2进制文件obj。最后编译器再利用link把用到的函数变量等链接起来生成可执行文件exe。这就是编译的过程。
但是这个过程在遇到模板类时候会发生一些变化,如果编译器能将模板类的实现函数编译成obj文件,那么在这些函数中遇到 Type(类型位置),编译器该怎么将代码翻译成对应的汇编代码呢,一些pull,push该对应多少字节呢,这些都是未知的,所以从理论上讲,即便我们将模板类的声明和实现相互分离,但是在生成的对应obj文件中不会有一个函数的2进制代码的。
类模板的特殊编译:
那么既然obj中没有二进制函数,main函数又是如何调用模板类中的函数呢,我们知道一般的类,main函数调用它只需要知道一个link地址就行,但是针对模板类就不一样了,它会在main函数所在的cpp里面把用到的函数实例化(就是用具体类型替换通用类型),这样就可以调用它了,因为要替换,所以就必须知道函数的定义了,这就是为什么必须得在一个文件中实现模板类的声明和定义。

测试和验证:
  1. template<typename Type>
  2. void Stacks<Type>::print()
  3. {
  4.         cout<<"This is a test ,I love you"
  5.                 <<"I love you,I love you"<<endl;
  6. }
复制代码
然后我们在main中调用print函数,在生成的debug文件中用notepad++打开main.obj,我们可以看到有这样的字符出现:
1.png
这就说明了问题,main.cpp中实例化了函数的定义。

附带栈结构实现的C++源代码
Stacks.h
  1. // Stacks.h
  2. #pragma once
  3. #include <iostream>
  4. using namespace std;

  5. template<typename Type>
  6. class Stacks
  7. {
  8. public:
  9.         Stacks(void);
  10.         Stacks(int nSize);
  11.         Stacks(Type Arr[],int nSize);
  12.         ~Stacks(void);
  13. public:
  14.         bool isEmpty();
  15.         bool isFull();
  16.         bool push(const Type &e);
  17.         Type pop();
  18.         Type getTop();
  19.         int  getLength();
  20.         void print();
  21. private:
  22.         int m_top;
  23.         int m_nLength;
  24.         Type *m_pArr;
  25.        
  26. };

  27. template<typename Type>
  28. Stacks<Type>::Stacks(void)
  29. {
  30.         m_top = -1;
  31.         m_nLength = 10;
  32.         m_pArr = new Type[10];
  33.         if (m_pArr == NULL)
  34.                 cout<<"Allocate stack failed"<<endl;
  35.         else
  36.                 m_top = m_nLength-1;       
  37. }

  38. template<typename Type>
  39. Stacks<Type>::Stacks(int nSize)
  40. {
  41.         m_top = -1;
  42.         m_pArr = new Type[nSize];
  43.         if(m_pArr == NULL)
  44.                 cout<<"Allocate stack failed"<<endl;
  45.         else
  46.         {
  47.                 m_top = nSize-1;
  48.                 m_nLength = nSize;
  49.         }
  50. }

  51. template<typename Type>
  52. Stacks<Type>::Stacks(Type Arr[],int nSize)
  53. {
  54.         m_top = -1;
  55.         m_pArr = new Type[nSize];
  56.         if(m_pArr == NULL)
  57.                 cout<<"Allocate stack failed"<<endl;
  58.         else
  59.         {
  60.                 for(int i=0;i<nSize;i++)
  61.                         m_pArr[i] = Arr[i];
  62.                 m_top = nSize - 1;
  63.                 m_nLength = nSize;
  64.         }
  65. }

  66. template<typename Type>
  67. bool Stacks<Type>::isEmpty()
  68. {
  69.         return m_top == -1;
  70. }

  71. template<typename Type>
  72. bool Stacks<Type>::isFull()
  73. {
  74.         return m_top == m_nLength - 1;
  75. }

  76. template<typename Type>
  77. Type Stacks<Type>::getTop()
  78. {
  79.         if (m_top != -1)
  80.                 return m_pArr[m_top];
  81.         else
  82.         {
  83.                 cout<<"The stack is empty"<<endl;
  84.                 exit(1);
  85.                
  86.         }
  87. }

  88. template<typename Type>
  89. Type Stacks<Type>::pop()
  90. {
  91.         if(m_top == -1)
  92.         {
  93.                 cout<<"The stack is empty"<<endl;
  94.                 exit(1);
  95.         }
  96.         else
  97.         {
  98.                 m_top--;
  99.                 return m_pArr[m_top+1];
  100.         }
  101. }

  102. template<typename Type>
  103. bool Stacks<Type>::push(const Type &e)
  104. {
  105.         if(m_top == m_nLength-1)
  106.         {
  107.                 cout<<"The stack is full"<<endl;
  108.                 return false;
  109.         }
  110.         else
  111.         {
  112.                 m_top++;
  113.                 m_pArr[m_top] = e;
  114.                 return true;
  115.         }
  116. }

  117. template<typename Type>
  118. int Stacks<Type>::getLength()
  119. {
  120.         return m_nLength;
  121. }

  122. template<typename Type>
  123. Stacks<Type>::~Stacks(void)
  124. {
  125.         if(m_pArr != NULL)
  126.         {
  127.                 delete m_pArr;
  128.                 m_pArr = NULL;
  129.         }

  130. }

  131. template<typename Type>
  132. void Stacks<Type>::print()
  133. {
  134.         cout<<"This is a test ,I love you"
  135.                 <<"I love you,I love you"<<endl;
  136. }

  137. //main.cpp
  138. #include<iostream>
  139. #include<string>
  140. #include"Stacks.h"
  141. using namespace std;
  142. void main()
  143. {
  144.         int a[7] = {1,2,3,4,5,6,7};

  145.         Stacks<int> Sta(a,7);
  146.         cout<<Sta.isFull()<<endl;
  147.        
  148.         for(int i=0;i<7;i++)
  149.         {
  150.                         int top = Sta.pop();
  151.                         cout<<"The top is:"<<top<<endl;
  152.         }

  153.         cout<<Sta.isEmpty()<<endl;
  154.         cout<<Sta.getLength()<<endl;

  155.         Sta.print();
  156.         Sta.print();

  157.         system("pause");
  158. }
复制代码
回复

使用道具 举报

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-4-19 23:28 , Processed in 0.040838 second(s), 34 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表