typename 的高级用法2

  1. // stack5.cpp : Defines the entry point for the console application.
  2. //
  3. #include "stdafx.h"
  4. #include <iostream>
  5. #include <deque>
  6. #include <string>
  7. #include <exception>
  8. using namespace std;
  9. template <class T>
  10. class CStack
  11. {
  12. public:
  13.     void push(T const&);
  14.     void pop();
  15.     T top() const;
  16.     bool empty() const;
  17.     template <class T2>
  18.     CStack<T>& operator = (CStack<T2> const&);
  19. private:
  20.     deque<T>    m_dqElems;  
  21. };
  22. template <class T>
  23. void CStack<T>::push(T const& elem)
  24. {
  25.     m_dqElems.push_back(elem);
  26. }
  27. template <class T>
  28. void CStack<T>::pop()
  29. {
  30.     if (m_dqElems.empty())
  31.     {
  32.         throw out_of_range("empty stack!");
  33.     }
  34.     m_dqElems.pop_back();
  35. }
  36. template <class T>
  37. T CStack<T>::top() const
  38. {
  39.     if (m_dqElems.empty())
  40.     {
  41.         throw out_of_range("empty stack!");
  42.     }
  43.     return m_dqElems.back();
  44. }
  45. template <class T>
  46. bool CStack<T>::empty() const
  47. {
  48.     return m_dqElems.empty();
  49. }
  50. template <class T>
  51. template <class T2>
  52. CStack<T>& CStack<T>::operator = (CStack<T2> const& op2)
  53. {
  54.     if ((void*)this == (void*)&op2)// 判断是否赋值给自己
  55.     {
  56.         return *this;
  57.     }
  58.     CStack<T2> tmpOp2(op2);// 建立 op2 的一份拷贝
  59.     m_dqElems.clear(); // 移除所有现有元素
  60.     while (!tmpOp2.empty())
  61.     {
  62.         m_dqElems.push_front(tmpOp2.top());
  63.         tmpOp2.pop();
  64.     }
  65.     return *this;
  66. }
  67. int _tmain(int argc, _TCHAR* argv[])
  68. {
  69.     int i = 0;
  70.     CStack<int> intStack;
  71.     CStack<float> floatStack;
  72.     for (i = 0; i < 10; i++)
  73.     {
  74.         intStack.push(i);
  75.     }
  76.     floatStack = intStack;
  77.     cout << "floatStack contents: " << endl;
  78.     while (!floatStack.empty())
  79.     {
  80.         cout << floatStack.top() << "/t";
  81.         floatStack.pop();
  82.     }
  83.     cout << endl;
  84.     return 0;
  85. }


实作这个运算符(成员函数)时,你可能希望取得「赋值符号右侧之op2 stack」的所有必要资料,但是这个stack的类型和目前(此身)类型不同(是的,如果你以两个不同的类型实例化同一个classtemplate,你会得到两个不同的类型),所以只能通过public接口来得到那些数据。 因此惟一能够取得 op2 数据的办法就是调用其 top()函数。你必须经由 top()取得op2 的所有数据,而这必须借助 op2 的一份拷贝来实现:每取得一笔数据,就运用 pop()把该数据从op2 的拷贝中移除。由于top()传回的是stack之中最后(最晚)被推入的元素,所以我们需要反方向把元素安插回去。基于这种需求,这里使用了deque,它提供push_front()操作,可以把一 个元素安插到容器最前面。有了这个 member template,你就可以把一个 int stack 赋值(assign)给一个 float stack:

Stack<int> intStack1, intStack2; //stack for ints
Stack<float> floatStack; //stack for floats
...
floatStack = intStack1; // OK:两个 stacks 类型不同,但 int 可转型为 float。

当然,这个赋值动作并不会改动 stack和其元素的类型。赋值完成后,floatStack 的元素类型还是 float,而 top()仍然传回 float 值。也许你会认为,这么做会使得类型检查失效,因为你甚至可以把任意类型的元素赋值给另一个 stack。然而事实并非如此。必要的类型检查会在「来源端 stack」的元素(拷贝)被安插到「目 的端 stack」时进行:

elems.push_front(tmp.top());

如 果 你将一个 string stack 赋值 给一个 float stack , 以 上 述 句 编译时就会发生错 误: 「elems.push_front()无法接受 tmp.top()的返回类型」。具体的错误讯息因编译器而异,但 含义类似。

Stack<std::string> stringStack; // stack of strings
Stack<float> floatStack; // stack of floats
floatStack = stringStack; // 错误:std::string 无法转型为 float

注意,前述的 template assignment 运算符并不取代 default assignment 运算符。如果你在相同 类型的 stack 之间赋值,编译器还是会采用 default assignment 运算符。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值