Chinaunix首页 | 论坛 | 博客
  • 博客访问: 389217
  • 博文数量: 80
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 560
  • 用 户 组: 普通用户
  • 注册时间: 2015-03-10 08:38
文章分类
文章存档

2016年(32)

2015年(48)

我的朋友

分类: LINUX

2016-01-06 11:16:03

先拷一段代码, 出之于《C++程序设计教程》第二版,钱能主编.

  1. #include <iostream>
  2. using namespace std;

  3. template<typename T>
  4. class Node{
  5.     public:
  6.         Node(T& d):c(d),next(0),pref(0){}
  7.         T c;
  8.         Node *next,*pref;
  9.     };
  10.     
  11. template<typename T>
  12. class List{
  13.     Node<T> *first, *last;
  14.     public:
  15.         List();
  16.         void add(T& c);
  17.         void remove(T& c);
  18.         Node<T>* find(T& c);
  19.         void print();
  20.         ~List();
  21.     };
  22.     
  23. template<typename T>
  24. List<T>::List():first(0),last(0)
  25. {}

  26. template<typename T>
  27. void List<T>::add(T& n)
  28. {
  29.     Node<T>* p = new Node<T>(n);
  30.     p->next = first;
  31.     first = p;
  32.     (last?p->next->pref:last) = p;
  33. }

  34. template<typename T>
  35. void List<T>::remove(T& n)
  36. {
  37.     Node<T> *p = find(n);
  38.     if(!p) return;
  39.     (p->next?p->next->pref:last) = p->pref;
  40.     (p->pref?p->pref->next:first) = p->next;
  41.     delete p;
  42. }

  43. template<typename T>
  44. Node<T>* List<T>::find(T& n)
  45. {
  46.     for(Node<T> *p = first; p;p=p->next)
  47.     {
  48.         if(p->c == n) return p;
  49.     }
  50.     return 0;
  51. }

  52. template<typename T>
  53. List<T>::~List()
  54. {
  55.     for(Node<T> *p; p = first;delete p)
  56.         first = first->next;
  57. }

  58. template<typename T>
  59. void List<T>::print()
  60. {
  61.     for(Node<T>* p=first;p;p=p->next)
  62.         cout<< p->c<<" ";
  63.     cout<< "\n";
  64. }

  65. int main()
  66. {
  67.     List> dList;
  68.     double a = 3.6;
  69.     double b = 5.8;
  70.     dList.add(3.6);   //报错:main.cpp:77: error: no matching function for call to 'List::add(double)'
                          //    main.cpp:29: note: candidates are: void List::add(T&) [with T = double]

  71.     dList.add(5.8);   //报错:main.cpp:78: error: no matching function for call to 'List::add(double)'
                          //     main.cpp:29: note: candidates are: void List::add(T&) [with T = double]

  72.     dList.print();
  73.     
  74.     int c=5;
  75.     int d=8;
  76.     List<int> iList;
  77.     iList.add(c);
  78.     iList.add(d);
  79.     iList.print();
  80. }
这段代码出自类模版那一章, 用来定义一个链表的类模版. 但是我在编译到77,78行的时候出现了错误:
    main.cpp: In function 'int main()':
    main.cpp:77: error: no matching function for call to 'List::add(double)'
    main.cpp:29: note: candidates are: void List::add(T&) [with T = double]
    main.cpp:78: error: no matching function for call to 'List::add(double)'
    main.cpp:29: note: candidates are: void List::add(T&) [with T = double]

分析一下, 感觉好像也没什么问题, 3.6和5.8作为double型传入到double型的参数没问题呀.
但是我做了下面的实验之后, 就知道了.
把77行, 78行的参数改为下面这样:
    
  1. dList.add(a);
  2. dList.add(b);
编译就可以正常通过了!!!

这说明了一个问题, 直接传数字和传变量是不一样的!

c++在对待立即数, 是将其认为为const double型的, 而dList的定义中说的很明白其类型为double型.
而const double型和double型是不一样的!!! 所以编译会报错!

举例, 比如说这里我把dList的定义改为下面这样:

点击(此处)折叠或打开

  1. List<const double> dList;
那么就可以用
    dList.add(3.6);
    dList.add(5.8); 这种方式去调用了.


而且, 这里我做了个实验, 把dList的定义改为下面这样之后:

  1. List<const double> dList;
这种用法也是ok的:
  1. dList.add(a);
  2. dList.add(b);
因为, 这样相当于把a,b这两种double类型隐含转换成了const double类型, 只要保证a, b不会被改变就OK了.
我们可以做下面这个测试, 在void List::add(T& n)函数后面加上这么一行n=n+1;如下:
template
void List::add(T& n)
{
    Node* p = new Node(n);
    p->next = first;
    first = p;
    (last?p->next->pref:last) = p;
    n=n+1;
}
就会发现报这么一个编译错误:
main.cpp: In member function 'void List::add(T&) [with T = const double]':
main.cpp:78:   instantiated from here
main.cpp:35: error: assignment of read-only reference 'n'

所以!  在模版做类型转换的时候, 一定一定一定要注意!!!






阅读(1646) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~