当前位置:Gxlcms > mysql > C++关于模板之间的继承,导致的模板子类的成员看不到(cannot

C++关于模板之间的继承,导致的模板子类的成员看不到(cannot

时间:2021-07-01 10:21:17 帮助过:26人阅读

首先, 开门见山, 这个难题的解决办法是用this指针, 或者使用父类配合着scope resolution。 这个问题是我在学习linked list as an ADT , linked list 是含有纯虚函数, 所以是抽象基础类。 然后又linked list 继承出unordered linked list。 注意, 还可以

首先, 开门见山, 这个难题的解决办法是用this指针, 或者使用父类配合着scope resolution。

这个问题是我在学习linked list as an ADT , linked list 是含有纯虚函数, 所以是抽象基础类。 然后又linked list 继承出unordered linked list。 注意, 还可以由linked list 继承出ordered linked list。

言归正传, 出现问题的代码如下:

linkedlist.h 文件如下:

  1. #ifndef H_LinkedListType
  2. #define H_LinkedListType
  3. #include <iostream>
  4. #include <cassert>
  5. using namespace std;
  6. //Definition of the node
  7. template <class type="">
  8. struct nodeType
  9. {
  10. Type info;
  11. nodeType<type> *link;
  12. };
  13. template <class type="">
  14. class linkedListIterator
  15. {
  16. public:
  17. linkedListIterator();
  18. //Default constructor
  19. //Postcondition: current = NULL;
  20. linkedListIterator(nodeType<type> *ptr);
  21. //Constructor with a parameter.
  22. //Postcondition: current = ptr;
  23. Type operator*();
  24. //Function to overload the dereferencing operator *.
  25. //Postcondition: Returns the info contained in the node.
  26. linkedListIterator<type> operator++();
  27. //Overload the pre-increment operator.
  28. //Postcondition: The iterator is advanced to the next
  29. // node.
  30. bool operator==(const linkedListIterator<type>& right) const;
  31. //Overload the equality operator.
  32. //Postcondition: Returns true if this iterator is equal to
  33. // the iterator specified by right,
  34. // otherwise it returns the value false.
  35. bool operator!=(const linkedListIterator<type>& right) const;
  36. //Overload the not equal to operator.
  37. //Postcondition: Returns true if this iterator is not
  38. // equal to the iterator specified by
  39. // right; otherwise it returns the value
  40. // false.
  41. private:
  42. nodeType<type> *current; //pointer to point to the current
  43. //node in the linked list
  44. };
  45. template <class type="">
  46. linkedListIterator<type>::linkedListIterator()
  47. {
  48. current = NULL;
  49. }
  50. template <class type="">
  51. linkedListIterator<type>::
  52. linkedListIterator(nodeType<type> *ptr)
  53. {
  54. current = ptr;
  55. }
  56. template <class type="">
  57. Type linkedListIterator<type>::operator*()
  58. {
  59. return current->info;
  60. }
  61. template <class type="">
  62. linkedListIterator<type> linkedListIterator<type>::operator++()
  63. {
  64. current = current->link;
  65. return *this;
  66. }
  67. template <class type="">
  68. bool linkedListIterator<type>::operator==
  69. (const linkedListIterator<type>& right) const
  70. {
  71. return (current == right.current);
  72. }
  73. template <class type="">
  74. bool linkedListIterator<type>::operator!=
  75. (const linkedListIterator<type>& right) const
  76. { return (current != right.current);
  77. }
  78. //***************** class linkedListType ****************
  79. template <class type="">
  80. class linkedListType
  81. {
  82. public:
  83. const linkedListType<type>& operator=
  84. (const linkedListType<type>&);
  85. //Overload the assignment operator.
  86. void initializeList();
  87. //Initialize the list to an empty state.
  88. //Postcondition: first = NULL, last = NULL, count = 0;
  89. bool isEmptyList() const;
  90. //Function to determine whether the list is empty.
  91. //Postcondition: Returns true if the list is empty,
  92. // otherwise it returns false.
  93. void print() const;
  94. //Function to output the data contained in each node.
  95. //Postcondition: none
  96. int length() const;
  97. //Function to return the number of nodes in the list.
  98. //Postcondition: The value of count is returned.
  99. void destroyList();
  100. //Function to delete all the nodes from the list.
  101. //Postcondition: first = NULL, last = NULL, count = 0;
  102. Type front() const;
  103. //Function to return the first element of the list.
  104. //Precondition: The list must exist and must not be
  105. // empty.
  106. //Postcondition: If the list is empty, the program
  107. // terminates; otherwise, the first
  108. // element of the list is returned.
  109. Type back() const;
  110. //Function to return the last element of the list.
  111. //Precondition: The list must exist and must not be
  112. // empty.
  113. //Postcondition: If the list is empty, the program
  114. // terminates; otherwise, the last
  115. // element of the list is returned.
  116. virtual bool search(const Type& searchItem) const = 0;
  117. //Function to determine whether searchItem is in the list.
  118. //Postcondition: Returns true if searchItem is in the
  119. // list, otherwise the value false is
  120. // returned.
  121. virtual void insertFirst(const Type& newItem) = 0;
  122. //Function to insert newItem at the beginning of the list.
  123. //Postcondition: first points to the new list, newItem is
  124. // inserted at the beginning of the list,
  125. // last points to the last node in the list,
  126. // and count is incremented by 1.
  127. virtual void insertLast(const Type& newItem) = 0;
  128. //Function to insert newItem at the end of the list.
  129. //Postcondition: first points to the new list, newItem
  130. // is inserted at the end of the list,
  131. // last points to the last node in the list,
  132. // and count is incremented by 1.
  133. virtual void deleteNode(const Type& deleteItem) = 0;
  134. //Function to delete deleteItem from the list.
  135. //Postcondition: If found, the node containing
  136. // deleteItem is deleted from the list.
  137. // first points to the first node, last
  138. // points to the last node of the updated
  139. // list, and count is decremented by 1.
  140. linkedListIterator<type> begin();
  141. //Function to return an iterator at the begining of the
  142. //linked list.
  143. //Postcondition: Returns an iterator such that current is
  144. // set to first.
  145. linkedListIterator<type> end();
  146. //Function to return an iterator one element past the
  147. //last element of the linked list.
  148. //Postcondition: Returns an iterator such that current is
  149. // set to NULL.
  150. linkedListType();
  151. //default constructor
  152. //Initializes the list to an empty state.
  153. //Postcondition: first = NULL, last = NULL, count = 0;
  154. linkedListType(const linkedListType<type>& otherList);
  155. //copy constructor
  156. ~linkedListType();
  157. //destructor
  158. //Deletes all the nodes from the list.
  159. //Postcondition: The list object is destroyed.
  160. protected:
  161. int count; //variable to store the number of
  162. //elements in the list
  163. nodeType<type> *first; //pointer to the first node of the list
  164. nodeType<type> *last; //pointer to the last node of the list
  165. private:
  166. void copyList(const linkedListType<type>& otherList);
  167. //Function to make a copy of otherList.
  168. //Postcondition: A copy of otherList is created and
  169. // assigned to this list.
  170. };
  171. template <class type="">
  172. bool linkedListType<type>::isEmptyList() const
  173. {
  174. return(first == NULL);
  175. }
  176. template <class type="">
  177. linkedListType<type>::linkedListType() //default constructor
  178. {
  179. first = NULL;
  180. last = NULL;
  181. count = 0;
  182. }
  183. template <class type="">
  184. void linkedListType<type>::destroyList()
  185. {
  186. nodeType<type> *temp; //pointer to deallocate the memory
  187. //occupied by the node
  188. while (first != NULL) //while there are nodes in the list
  189. {
  190. temp = first; //set temp to the current node
  191. first = first->link; //advance first to the next node
  192. delete temp; //deallocate the memory occupied by temp
  193. }
  194. last = NULL; //initialize last to NULL; first has already
  195. //been set to NULL by the while loop
  196. count = 0;
  197. }
  198. template <class type="">
  199. void linkedListType<type>::initializeList()
  200. {
  201. destroyList(); //if the list has any nodes, delete them
  202. }
  203. template <class type="">
  204. void linkedListType<type>::print() const
  205. {
  206. nodeType<type> *current; //pointer to traverse the list
  207. current = first; //set current so that it points to
  208. //the first node
  209. while (current != NULL) //while more data to print
  210. {
  211. cout << current->info << " ";
  212. current = current->link;
  213. }
  214. }//end print
  215. template <class type="">
  216. int linkedListType<type>::length() const
  217. {
  218. return count;
  219. } //end length
  220. template <class type="">
  221. Type linkedListType<type>::front() const
  222. {
  223. assert(first != NULL);
  224. return first->info; //return the info of the first node
  225. }//end front
  226. template <class type="">
  227. Type linkedListType<type>::back() const
  228. {
  229. assert(last != NULL);
  230. return last->info; //return the info of the last node
  231. }//end back
  232. template <class type="">
  233. linkedListIterator<type> linkedListType<type>::begin()
  234. {
  235. linkedListIterator<type> temp(first);
  236. return temp;
  237. }
  238. template <class type="">
  239. linkedListIterator<type> linkedListType<type>::end()
  240. {
  241. linkedListIterator<type> temp(NULL);
  242. return temp;
  243. }
  244. template <class type="">
  245. void linkedListType<type>::copyList
  246. (const linkedListType<type>& otherList)
  247. {
  248. nodeType<type> *newNode; //pointer to create a node
  249. nodeType<type> *current; //pointer to traverse the list
  250. if (first != NULL) //if the list is nonempty, make it empty
  251. destroyList();
  252. if (otherList.first == NULL) //otherList is empty
  253. {
  254. first = NULL;
  255. last = NULL;
  256. count = 0;
  257. }
  258. else
  259. {
  260. current = otherList.first; //current points to the
  261. //list to be copied
  262. count = otherList.count;
  263. //copy the first node
  264. first = new nodeType<type>; //create the node
  265. first->info = current->info; //copy the info
  266. first->link = NULL; //set the link field of
  267. //the node to NULL
  268. last = first; //make last point to the
  269. //first node
  270. current = current->link; //make current point to
  271. //the next node
  272. //copy the remaining list
  273. while (current != NULL)
  274. {
  275. newNode = new nodeType<type>; //create a node
  276. newNode->info = current->info; //copy the info
  277. newNode->link = NULL; //set the link of
  278. //newNode to NULL
  279. last->link = newNode; //attach newNode after last
  280. last = newNode; //make last point to
  281. //the actual last node
  282. current = current->link; //make current point
  283. //to the next node
  284. }//end while
  285. }//end else
  286. }//end copyList
  287. template <class type="">
  288. linkedListType<type>::~linkedListType() //destructor
  289. {
  290. destroyList();
  291. }//end destructor
  292. template <class type="">
  293. linkedListType<type>::linkedListType
  294. (const linkedListType<type>& otherList)
  295. {
  296. first = NULL;
  297. copyList(otherList);
  298. }//end copy constructor
  299. //overload the assignment operator
  300. template <class type="">
  301. const linkedListType<type>& linkedListType<type>::operator=
  302. (const linkedListType<type>& otherList)
  303. {
  304. if (this != &otherList) //avoid self-copy
  305. {
  306. copyList(otherList);
  307. }//end else
  308. return *this;
  309. }
  310. #endif
  311. </type></type></type></class></type></type></class></type></class></type></type></type></type></type></type></class></type></type></type></class></type></type></type></class></type></class></type></class></type></class></type></type></class></type></class></type></type></class></type></class></type></class></type></type></type></type></type></type></type></type></class></type></type></class></type></type></class></type></type></class></type></class></type></type></class></type></class></type></type></type></type></type></class></type></class></cassert></iostream>

unorderedLinkedList.h文件如下:

  1. #ifndef H_UnorderedLinkedList
  2. #define H_UnorderedLinkedList
  3. #include "linkedList.h"
  4. using namespace std;
  5. template <class type="">
  6. class unorderedLinkedList: public linkedListType<type>
  7. {
  8. public:
  9. bool search(const Type& searchItem) const;
  10. //Function to determine whether searchItem is in the list.
  11. //Postcondition: Returns true if searchItem is in the
  12. // list, otherwise the value false is
  13. // returned.
  14. void insertFirst(const Type& newItem);
  15. //Function to insert newItem at the beginning of the list.
  16. //Postcondition: first points to the new list, newItem is
  17. // inserted at the beginning of the list,
  18. // last points to the last node in the
  19. // list, and count is incremented by 1.
  20. void insertLast(const Type& newItem);
  21. //Function to insert newItem at the end of the list.
  22. //Postcondition: first points to the new list, newItem
  23. // is inserted at the end of the list,
  24. // last points to the last node in the
  25. // list, and count is incremented by 1.
  26. void deleteNode(const Type& deleteItem);
  27. //Function to delete deleteItem from the list.
  28. //Postcondition: If found, the node containing
  29. // deleteItem is deleted from the list.
  30. // first points to the first node, last
  31. // points to the last node of the updated
  32. // list, and count is decremented by 1.
  33. };
  34. template <class type="">
  35. bool unorderedLinkedList<type>::
  36. search(const Type& searchItem) const
  37. {
  38. nodeType<type> *current; //pointer to traverse the list
  39. bool found = false;
  40. current = first; //set current to point to the first
  41. //node in the list
  42. while (current != NULL && !found) //search the list
  43. if (current->info == searchItem) //searchItem is found
  44. found = true;
  45. else
  46. current = current->link; //make current point to
  47. //the next node
  48. return found;
  49. }//end search
  50. template <class type="">
  51. void unorderedLinkedList<type>::insertFirst(const Type& newItem)
  52. {
  53. nodeType<type> *newNode; //pointer to create the new node
  54. newNode = new nodeType<type>; //create the new node
  55. newNode->info = newItem; //store the new item in the node
  56. newNode->link = this -> first; //insert newNode before first
  57. first = newNode; //make first point to the
  58. //actual first node
  59. count++; //increment count
  60. if (last == NULL) //if the list was empty, newNode is also
  61. //the last node in the list
  62. last = newNode;
  63. }//end insertFirst
  64. template <class type="">
  65. void unorderedLinkedList<type>::insertLast(const Type& newItem)
  66. {
  67. nodeType<type> *newNode; //pointer to create the new node
  68. newNode = new nodeType<type>; //create the new node
  69. newNode->info = newItem; //store the new item in the node
  70. newNode->link = NULL; //set the link field of newNode
  71. //to NULL
  72. if ( first == NULL) //if the list is empty, newNode is
  73. //both the first and last node
  74. {
  75. first = newNode;
  76. last = newNode;
  77. count++; //increment count
  78. }
  79. else //the list is not empty, insert newNode after last
  80. {
  81. last->link = newNode; //insert newNode after last
  82. last = newNode; //make last point to the actual
  83. //last node in the list
  84. count++; //increment count
  85. }
  86. }//end insertLast
  87. template <class type="">
  88. void unorderedLinkedList<type>::deleteNode(const Type& deleteItem)
  89. {
  90. nodeType<type> *current; //pointer to traverse the list
  91. nodeType<type> *trailCurrent; //pointer just before current
  92. bool found;
  93. if (first == NULL) //Case 1; the list is empty.
  94. cout << "Cannot delete from an empty list."
  95. << endl;
  96. else
  97. {
  98. if (first->info == deleteItem) //Case 2
  99. {
  100. current = first;
  101. first = first->link;
  102. count--;
  103. if (first == NULL) //the list has only one node
  104. last = NULL;
  105. delete current;
  106. }
  107. else //search the list for the node with the given info
  108. {
  109. found = false;
  110. trailCurrent = first; //set trailCurrent to point
  111. //to the first node
  112. current = first->link; //set current to point to
  113. //the second node
  114. while (current != NULL && !found)
  115. {
  116. if (current->info != deleteItem)
  117. {
  118. trailCurrent = current;
  119. current = current-> link;
  120. }
  121. else
  122. found = true;
  123. }//end while
  124. if (found) //Case 3; if found, delete the node
  125. {
  126. trailCurrent->link = current->link;
  127. this -> count--;
  128. if (last == current) //node to be deleted
  129. //was the last node
  130. last = trailCurrent; //update the value
  131. //of last
  132. delete current; //delete the node from the list
  133. }
  134. else
  135. cout << "The item to be deleted is not in "
  136. << "the list." << endl;
  137. }//end else
  138. }//end else
  139. }//end deleteNode
  140. #endif
  141. </type></type></type></class></type></type></type></class></type></type></type></class></type></type></class></type></class>

主程序如下main.cpp:

  1. //This program tests various operation of a linked list
  2. //34 62 21 90 66 53 88 24 10 -999
  3. #include <iostream>
  4. #include "unorderedLinkedList.h"
  5. using namespace std;
  6. int main()
  7. {
  8. unorderedLinkedList<int> list1, list2; //Line 1
  9. int num; //Line 2
  10. cout << "Line 3: Enter integers ending "
  11. << "with -999" << endl; //Line 3
  12. cin >> num; //Line 4
  13. while (num != -999) //Line 5
  14. {
  15. list1.insertLast(num); //Line 6
  16. cin >> num; //Line 7
  17. }
  18. cout << endl; //Line 8
  19. cout << "Line 9: list1: "; //Line 9
  20. list1.print(); //Line 10
  21. cout << endl; //Line 11
  22. cout << "Line 12: Length of list1: "
  23. << list1.length() << endl; //Line 12
  24. list2 = list1;
  25. //test the assignment operator Line 13
  26. cout << "Line 16: list2: "; //Line 14
  27. list2.print(); //Line 15
  28. cout << endl; //Line 16
  29. cout << "Line 17: Length of list2: "
  30. << list2.length() << endl; //Line 17
  31. cout << "Line 18: Enter the number to be "
  32. << "deleted: "; //Line 18
  33. cin >> num; //Line 19
  34. cout << endl; //Line 20
  35. list2.deleteNode(num); //Line 21
  36. cout << "Line 22: After deleting " << num
  37. << " list2: " << endl; //Line 22
  38. list2.print(); //Line 23
  39. cout << endl; //Line 24
  40. cout << "Line 25: Length of list2: "
  41. << list2.length() << endl; //Line 25
  42. cout << endl << "Line 26: Output list1 "
  43. << "using an iterator" << endl; //LIne 26
  44. linkedListIterator<int> it; //Line 27
  45. for (it = list1.begin(); it != list1.end();
  46. ++it) //Line 28
  47. cout << *it << " "; //Line 29
  48. cout << endl; //Line 30
  49. return 0;
  50. }</int></int></iostream>

编译结果error message 如下:



错误分析: 按照标准看, 上述的错误似乎有点问题。 因为first, last, count 都是父类的成员变量。 存取类型是protected。 我们的子类unorderedLinkedList 类是公开方式(public)继承linkedList。按说子类即unorderedLinkedList 的成员函数(虚函数)当然可以access 父类的protected 成员变量。 但是在这里出错了。 为什么呢?


原因是我们这里是模板类之间的继承。 如果是正常的普通类之间的继承, 结果一定是没有问题的。 当然access会通过, 编译会okay。 但是这里是模本类之间的继承。

在这里, 我们需要使用this 指针, 也可以使用scope resolution解决模板类之间的继承时变量访问的问题。 下面我们修改unorderedLinkedList.h 如下:

将模板成员函数定义count, first, last 分别用this -> count, this -> first, this -> last(第二中解决办法是换为linkedListType::first, linkedListType::count,linkedListType::last)。 不光如此, 当在子类中调用模板父类的成员函数的时候, 也要使用this 指针或者用scope resotion 解决这个问题。


  1. #ifndef H_UnorderedLinkedList
  2. #define H_UnorderedLinkedList
  3. #include "linkedList.h"
  4. using namespace std;
  5. template <class type="">
  6. class unorderedLinkedList: public linkedListType<type>
  7. {
  8. public:
  9. bool search(const Type& searchItem) const;
  10. //Function to determine whether searchItem is in the list.
  11. //Postcondition: Returns true if searchItem is in the
  12. // list, otherwise the value false is
  13. // returned.
  14. void insertFirst(const Type& newItem);
  15. //Function to insert newItem at the beginning of the list.
  16. //Postcondition: first points to the new list, newItem is
  17. // inserted at the beginning of the list,
  18. // last points to the last node in the
  19. // list, and count is incremented by 1.
  20. void insertLast(const Type& newItem);
  21. //Function to insert newItem at the end of the list.
  22. //Postcondition: first points to the new list, newItem
  23. // is inserted at the end of the list,
  24. // last points to the last node in the
  25. // list, and count is incremented by 1.
  26. void deleteNode(const Type& deleteItem);
  27. //Function to delete deleteItem from the list.
  28. //Postcondition: If found, the node containing
  29. // deleteItem is deleted from the list.
  30. // first points to the first node, last
  31. // points to the last node of the updated
  32. // list, and count is decremented by 1.
  33. };
  34. template <class type="">
  35. bool unorderedLinkedList<type>::
  36. search(const Type& searchItem) const
  37. {
  38. nodeType<type> *current; //pointer to traverse the list
  39. bool found = false;
  40. current = this -> first; //set current to point to the first
  41. //node in the list
  42. while (current != NULL && !found) //search the list
  43. if (current->info == searchItem) //searchItem is found
  44. found = true;
  45. else
  46. current = current->link; //make current point to
  47. //the next node
  48. return found;
  49. }//end search
  50. template <class type="">
  51. void unorderedLinkedList<type>::insertFirst(const Type& newItem)
  52. {
  53. nodeType<type> *newNode; //pointer to create the new node
  54. newNode = new nodeType<type>; //create the new node
  55. newNode->info = newItem; //store the new item in the node
  56. newNode->link = this -> first; //insert newNode before first
  57. this -> first = newNode; //make first point to the
  58. //actual first node
  59. this -> count++; //increment count
  60. if (this -> last == NULL) //if the list was empty, newNode is also
  61. //the last node in the list
  62. this -> last = newNode;
  63. }//end insertFirst
  64. template <class type="">
  65. void unorderedLinkedList<type>::insertLast(const Type& newItem)
  66. {
  67. nodeType<type> *newNode; //pointer to create the new node
  68. newNode = new nodeType<type>; //create the new node
  69. newNode->info = newItem; //store the new item in the node
  70. newNode->link = NULL; //set the link field of newNode
  71. //to NULL
  72. if ( this -> first == NULL) //if the list is empty, newNode is
  73. //both the first and last node
  74. {
  75. this -> first = newNode;
  76. this -> last = newNode;
  77. this -> count++; //increment count
  78. }
  79. else //the list is not empty, insert newNode after last
  80. {
  81. this -> last->link = newNode; //insert newNode after last
  82. this -> last = newNode; //make last point to the actual
  83. //last node in the list
  84. this -> count++; //increment count
  85. }
  86. }//end insertLast
  87. template <class type="">
  88. void unorderedLinkedList<type>::deleteNode(const Type& deleteItem)
  89. {
  90. nodeType<type> *current; //pointer to traverse the list
  91. nodeType<type> *trailCurrent; //pointer just before current
  92. bool found;
  93. if (this -> first == NULL) //Case 1; the list is empty.
  94. cout << "Cannot delete from an empty list."
  95. << endl;
  96. else
  97. {
  98. if (this -> first->info == deleteItem) //Case 2
  99. {
  100. current = this -> first;
  101. this -> first = this -> first->link;
  102. this -> count--;
  103. if (this -> first == NULL) //the list has only one node
  104. this -> last = NULL;
  105. delete current;
  106. }
  107. else //search the list for the node with the given info
  108. {
  109. found = false;
  110. trailCurrent = this -> first; //set trailCurrent to point
  111. //to the first node
  112. current = this -> first->link; //set current to point to
  113. //the second node
  114. while (current != NULL && !found)
  115. {
  116. if (current->info != deleteItem)
  117. {
  118. trailCurrent = current;
  119. current = current-> link;
  120. }
  121. else
  122. found = true;
  123. }//end while
  124. if (found) //Case 3; if found, delete the node
  125. {
  126. trailCurrent->link = current->link;
  127. this -> count--;
  128. if (this -> last == current) //node to be deleted
  129. //was the last node
  130. this -> last = trailCurrent; //update the value
  131. //of last
  132. delete current; //delete the node from the list
  133. }
  134. else
  135. cout << "The item to be deleted is not in "
  136. << "the list." << endl;
  137. }//end else
  138. }//end else
  139. }//end deleteNode
  140. #endif
  141. </type></type></type></class></type></type></type></class></type></type></type></class></type></type></class></type></class>

编译通过, 运行结果如下:




关于这个模板继承, 子类使用父类的成员是使用this, 或者scope resolution, 解释如下:

//To make the code valid either use this->f(), or Base::f(). Using the -fpermissive flag will also
//let the compiler accept the code, by marking all function calls for which no declaration is visible
//at the time of definition of the template for later lookup at instantiation time, as if it were a
//dependent call. We do not recommend using -fpermissive to work around invalid code, and it will also
//only catch cases where functions in base classes are called, not where variables in base classes are
//used (as in the example above).
//
//Note that some compilers (including G++ versions prior to 3.4) get these examples wrong and accept above
//code without an error. Those compilers do not implement two-stage name lookup correctly.
//


接下来是我在stack overflow 网站上得到的解答:

人气教程排行