免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3901 | 回复: 5
打印 上一主题 下一主题

[C++] C++ Primer Plus(5th) 的错误,完全无法编译?求高手 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-09-27 22:29 |只看该作者 |倒序浏览
本帖最后由 k8king 于 2011-09-27 23:29 编辑

C++ Primer Plus (第五版) 中文版,508页,14.4节:类模板
程序清单 14.13 stacktp.h
程序清单 14.14 stacktem.cpp

本来是模板类的例子,模拟的是堆栈,但是在小节 14.4.3 深入讨论模板类中将 string po 依次替换为 char * po; char po[40]; char * po = new char[40];
书里意思的替换方案一能够通过编译,但是运行可能会崩溃,实际实验无法通过编译。
书里意思的替换方案二无法通过编译,实际实验确实如此。我对书上关于无法通过的描述理解为数组名属于常量,无法被赋值,不知道理解的是否有所偏颇。
书里意思的替换方案三能够通过编译,但是只能保存最后一次输入的值,实际实验无法通过编译。
实际编码与书上的叙述无法吻合,难道是C++的标准进化了吗?
本人才疏学浅,对于替换方案1、2、3中实际编码无法通过的理由尚无法完全理解,版区卧虎藏龙,可否请高手不吝赐教?
附上代码如下:

header部分:
  1. //stacktp.h -- a stack template
  2. #ifndef STACKTP_H_INCLUDED
  3. #define STACKTP_H_INCLUDED
  4. template <typename Type>
  5. class Stack
  6. {
  7. private:
  8.     enum{MAX = 10};     //constant specific to class
  9.     Type items[MAX];    //holds stack items
  10.     int top;            //index for top stack item
  11. public:
  12.     Stack();
  13.     bool isempty();
  14.     bool isfull();
  15.     bool push(const Type & item);    //add item to stack
  16.     bool pop(Type & Item);           //pop top into item
  17. };

  18. template <typename Type>
  19. Stack<Type>::Stack()
  20. {
  21.     top = 0;
  22. }

  23. template<typename Type>
  24. bool Stack<Type>::isempty()
  25. {
  26.     return top == 0;
  27. }

  28. template <typename Type>
  29. bool Stack<Type>::isfull()
  30. {
  31.     return top == MAX;
  32. }

  33. template <typename Type>
  34. bool Stack<Type>::push(const Type & item)
  35. {
  36.     if(top < MAX)
  37.     {
  38.         items[top] = item;
  39.         top++;
  40.         return true;
  41.     }
  42.     else
  43.     {
  44.         return false;
  45.     }
  46. }

  47. template <typename Type>
  48. bool Stack<Type>::pop(Type & item)
  49. {
  50.     if(top > 0)
  51.     {
  52.         top--;
  53.         item = items[top];
  54.         return true;
  55.     }
  56.     else
  57.     {
  58.         return false;
  59.     }
  60. }

  61. #endif
复制代码
source部分:
  1. //stacktem.cpp -- testing the template stack class
  2. #include <iostream>
  3. #include <string>
  4. #include <cctype>
  5. #include "stacktp.h"
  6. using std::cin;
  7. using std::cout;

  8. int main()
  9. {
  10.     Stack<std::string> st;  //create an empty stack
  11.     char ch;
  12.     std::string po;
  13.     //char *po;
  14.     //char po[40];
  15.     //char * po = new char[40];
  16.     cout<< "Please enter A to add a purchase order.\n"
  17.         << "P to process a PO,or Q to Quit.\n";
  18.     while(cin >> ch && std::toupper(ch)!='Q')
  19.     {
  20.         while(cin.get()!='\n')
  21.         {
  22.             continue;
  23.         }
  24.         if(!std::isalpha(ch))
  25.         {
  26.             cout<<'\a';
  27.             continue;
  28.         }
  29.         switch(ch)
  30.         {
  31.             case 'A':
  32.             case 'a':
  33.             {
  34.                 cout<<"Enter a PO number to add:";
  35.                 cin>>po;
  36.                 if(st.isfull())
  37.                 {
  38.                     cout<<"stack already full\n.";
  39.                 }
  40.                 else
  41.                 {
  42.                     st.push(po);
  43.                 }
  44.                 break;
  45.             }
  46.             case 'P':
  47.             case 'p':
  48.             {
  49.                 if(st.isempty())
  50.                 {
  51.                     cout<<"stack already empty\n";
  52.                 }
  53.                 else
  54.                 {
  55.                     st.pop(po);
  56.                     cout<<"PO #"<<po<<" poped.\n";
  57.                 }
  58.                 break;
  59.             }
  60.         }
  61.         cout<< "Please enter A to add a purchase order.\n"
  62.         << "P to process a PO,or Q to Quit.\n";
  63.     }
  64.     cout << "Bye\n";
  65.     return 0;
  66. }
复制代码

论坛徽章:
0
2 [报告]
发表于 2011-09-28 15:58 |只看该作者
自己顶
是问题太简单,大家都不屑于回答,还是大家都不会?

论坛徽章:
0
3 [报告]
发表于 2011-09-28 16:35 |只看该作者
本帖最后由 狗蛋 于 2011-09-28 17:02 编辑

你理解错了。

书中的意思是连这个声明(不仅仅是po的声明)也要替换:
Stack<std::string> st;

不然参数类型都不对,怎么通过编译?



全部替换后,有:

对char * po,栈可以保存po当前的值;但这个值可能是随机的,读写操作会访问未知内存,故可以通过编译,但执行可能崩溃。

对 char po[40],因为C/C++语言本身不支持数组拷贝,而push/pop操作都要用到拷贝操作(或拷贝运算符),故无法通过编译。

对 char * po = new char[40],push/pop操作的是po里面保存的那个地址,并不涉及该地址保存的内容;所以一旦执行cin,po指向地址的内容就会被改写;既然栈里面保存的只是po指向的地址,那么输出内容当然就是被改写过的内容,表现就是“能够通过编译,但是只能保存最后一次输入的值”。


PS;看书的时候,多想想每句话的物理意义,注意把话里每个概念的含义都理解透彻。

你会问这个问题,原因是不理解 Stack<std::string> st 这个声明的真正含义——更准确点说,是完全不理解c/c++类型系统的含义,更不理解c/c++内存模型——然后自然无法理解作者举这个例子的用意何在,哪怕编译器已经明白无误的把错误写给你看。

你的概念掌握水平,显然还不适合去看这样的代码。

另外,看代码绝对不是学习的捷径,甚至可能是越学越晕的不二法门。
好的书也绝对不会告诉你“代码比人类语言更好理解,所以理解不了人话就看代码吧”;相反,好书会用人类语言先教会你“如何用代码来表达思路”,同时还会把思路教给你。

不要看不起前面那些小儿科的简单知识。不通过上机实验等手段,把这些基础概念一一掌握,是不可能达到“只要你敢说出思路,我就能给出实现代码”的水平的(当你看到模板的时候,应该是已经达到这个水平了的,如果能坚持把前面的基础概念都彻底弄明白的话)。

至于后面这样的“高级”代码,其实不过是基础知识的简单组合而已。在基础知识牢固掌握之后,反而没什么必要逐个实验。

论坛徽章:
0
4 [报告]
发表于 2011-09-28 17:39 |只看该作者
你理解错了。

书中的意思是连这个声明(不仅仅是po的声明)也要替换:
Stack st;

不然参数类型都不对 ...
狗蛋 发表于 2011-09-28 16:35



   

论坛徽章:
0
5 [报告]
发表于 2011-09-28 18:11 |只看该作者
回复 3# 狗蛋


确实是这个样子的,对于您的指导,感谢不已。前面确实看的太快了,本来只是想先选本书了解一下体系结构作为入门,但是后来只能硬着头皮上了。对于您指出的不足,虚心接受,我会努力的夯实基础的。
不过我现在还有一个疑问,就是对于char po[40]这种情况,您所说的拷贝操作,就是 赋值 吧?

论坛徽章:
0
6 [报告]
发表于 2011-09-28 19:03 |只看该作者
本帖最后由 狗蛋 于 2011-09-28 19:07 编辑

回复 5# k8king


    是。

string有重载=运算符,所以可以在这个stack的push/pop中使用;原生指针则原生支持=操作,所以也可以使用;但原生数组语言并不能支持=操作,所以:
char a[40]="sth"
char b[40]=a      //编译错误
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP