时间: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 文件如下:
- #ifndef H_LinkedListType
- #define H_LinkedListType
- #include <iostream>
- #include <cassert>
- using namespace std;
- //Definition of the node
- template <class type="">
- struct nodeType
- {
- Type info;
- nodeType<type> *link;
- };
- template <class type="">
- class linkedListIterator
- {
- public:
- linkedListIterator();
- //Default constructor
- //Postcondition: current = NULL;
- linkedListIterator(nodeType<type> *ptr);
- //Constructor with a parameter.
- //Postcondition: current = ptr;
- Type operator*();
- //Function to overload the dereferencing operator *.
- //Postcondition: Returns the info contained in the node.
- linkedListIterator<type> operator++();
- //Overload the pre-increment operator.
- //Postcondition: The iterator is advanced to the next
- // node.
- bool operator==(const linkedListIterator<type>& right) const;
- //Overload the equality operator.
- //Postcondition: Returns true if this iterator is equal to
- // the iterator specified by right,
- // otherwise it returns the value false.
- bool operator!=(const linkedListIterator<type>& right) const;
- //Overload the not equal to operator.
- //Postcondition: Returns true if this iterator is not
- // equal to the iterator specified by
- // right; otherwise it returns the value
- // false.
- private:
- nodeType<type> *current; //pointer to point to the current
- //node in the linked list
- };
- template <class type="">
- linkedListIterator<type>::linkedListIterator()
- {
- current = NULL;
- }
- template <class type="">
- linkedListIterator<type>::
- linkedListIterator(nodeType<type> *ptr)
- {
- current = ptr;
- }
- template <class type="">
- Type linkedListIterator<type>::operator*()
- {
- return current->info;
- }
- template <class type="">
- linkedListIterator<type> linkedListIterator<type>::operator++()
- {
- current = current->link;
- return *this;
- }
- template <class type="">
- bool linkedListIterator<type>::operator==
- (const linkedListIterator<type>& right) const
- {
- return (current == right.current);
- }
- template <class type="">
- bool linkedListIterator<type>::operator!=
- (const linkedListIterator<type>& right) const
- { return (current != right.current);
- }
- //***************** class linkedListType ****************
- template <class type="">
- class linkedListType
- {
- public:
- const linkedListType<type>& operator=
- (const linkedListType<type>&);
- //Overload the assignment operator.
- void initializeList();
- //Initialize the list to an empty state.
- //Postcondition: first = NULL, last = NULL, count = 0;
- bool isEmptyList() const;
- //Function to determine whether the list is empty.
- //Postcondition: Returns true if the list is empty,
- // otherwise it returns false.
- void print() const;
- //Function to output the data contained in each node.
- //Postcondition: none
- int length() const;
- //Function to return the number of nodes in the list.
- //Postcondition: The value of count is returned.
- void destroyList();
- //Function to delete all the nodes from the list.
- //Postcondition: first = NULL, last = NULL, count = 0;
- Type front() const;
- //Function to return the first element of the list.
- //Precondition: The list must exist and must not be
- // empty.
- //Postcondition: If the list is empty, the program
- // terminates; otherwise, the first
- // element of the list is returned.
- Type back() const;
- //Function to return the last element of the list.
- //Precondition: The list must exist and must not be
- // empty.
- //Postcondition: If the list is empty, the program
- // terminates; otherwise, the last
- // element of the list is returned.
- virtual bool search(const Type& searchItem) const = 0;
- //Function to determine whether searchItem is in the list.
- //Postcondition: Returns true if searchItem is in the
- // list, otherwise the value false is
- // returned.
- virtual void insertFirst(const Type& newItem) = 0;
- //Function to insert newItem at the beginning of the list.
- //Postcondition: first points to the new list, newItem is
- // inserted at the beginning of the list,
- // last points to the last node in the list,
- // and count is incremented by 1.
- virtual void insertLast(const Type& newItem) = 0;
- //Function to insert newItem at the end of the list.
- //Postcondition: first points to the new list, newItem
- // is inserted at the end of the list,
- // last points to the last node in the list,
- // and count is incremented by 1.
- virtual void deleteNode(const Type& deleteItem) = 0;
- //Function to delete deleteItem from the list.
- //Postcondition: If found, the node containing
- // deleteItem is deleted from the list.
- // first points to the first node, last
- // points to the last node of the updated
- // list, and count is decremented by 1.
- linkedListIterator<type> begin();
- //Function to return an iterator at the begining of the
- //linked list.
- //Postcondition: Returns an iterator such that current is
- // set to first.
- linkedListIterator<type> end();
- //Function to return an iterator one element past the
- //last element of the linked list.
- //Postcondition: Returns an iterator such that current is
- // set to NULL.
- linkedListType();
- //default constructor
- //Initializes the list to an empty state.
- //Postcondition: first = NULL, last = NULL, count = 0;
- linkedListType(const linkedListType<type>& otherList);
- //copy constructor
- ~linkedListType();
- //destructor
- //Deletes all the nodes from the list.
- //Postcondition: The list object is destroyed.
- protected:
- int count; //variable to store the number of
- //elements in the list
- nodeType<type> *first; //pointer to the first node of the list
- nodeType<type> *last; //pointer to the last node of the list
- private:
- void copyList(const linkedListType<type>& otherList);
- //Function to make a copy of otherList.
- //Postcondition: A copy of otherList is created and
- // assigned to this list.
- };
- template <class type="">
- bool linkedListType<type>::isEmptyList() const
- {
- return(first == NULL);
- }
- template <class type="">
- linkedListType<type>::linkedListType() //default constructor
- {
- first = NULL;
- last = NULL;
- count = 0;
- }
- template <class type="">
- void linkedListType<type>::destroyList()
- {
- nodeType<type> *temp; //pointer to deallocate the memory
- //occupied by the node
- while (first != NULL) //while there are nodes in the list
- {
- temp = first; //set temp to the current node
- first = first->link; //advance first to the next node
- delete temp; //deallocate the memory occupied by temp
- }
- last = NULL; //initialize last to NULL; first has already
- //been set to NULL by the while loop
- count = 0;
- }
- template <class type="">
- void linkedListType<type>::initializeList()
- {
- destroyList(); //if the list has any nodes, delete them
- }
- template <class type="">
- void linkedListType<type>::print() const
- {
- nodeType<type> *current; //pointer to traverse the list
- current = first; //set current so that it points to
- //the first node
- while (current != NULL) //while more data to print
- {
- cout << current->info << " ";
- current = current->link;
- }
- }//end print
- template <class type="">
- int linkedListType<type>::length() const
- {
- return count;
- } //end length
- template <class type="">
- Type linkedListType<type>::front() const
- {
- assert(first != NULL);
- return first->info; //return the info of the first node
- }//end front
- template <class type="">
- Type linkedListType<type>::back() const
- {
- assert(last != NULL);
- return last->info; //return the info of the last node
- }//end back
- template <class type="">
- linkedListIterator<type> linkedListType<type>::begin()
- {
- linkedListIterator<type> temp(first);
- return temp;
- }
- template <class type="">
- linkedListIterator<type> linkedListType<type>::end()
- {
- linkedListIterator<type> temp(NULL);
- return temp;
- }
- template <class type="">
- void linkedListType<type>::copyList
- (const linkedListType<type>& otherList)
- {
- nodeType<type> *newNode; //pointer to create a node
- nodeType<type> *current; //pointer to traverse the list
- if (first != NULL) //if the list is nonempty, make it empty
- destroyList();
- if (otherList.first == NULL) //otherList is empty
- {
- first = NULL;
- last = NULL;
- count = 0;
- }
- else
- {
- current = otherList.first; //current points to the
- //list to be copied
- count = otherList.count;
- //copy the first node
- first = new nodeType<type>; //create the node
- first->info = current->info; //copy the info
- first->link = NULL; //set the link field of
- //the node to NULL
- last = first; //make last point to the
- //first node
- current = current->link; //make current point to
- //the next node
- //copy the remaining list
- while (current != NULL)
- {
- newNode = new nodeType<type>; //create a node
- newNode->info = current->info; //copy the info
- newNode->link = NULL; //set the link of
- //newNode to NULL
- last->link = newNode; //attach newNode after last
- last = newNode; //make last point to
- //the actual last node
- current = current->link; //make current point
- //to the next node
- }//end while
- }//end else
- }//end copyList
- template <class type="">
- linkedListType<type>::~linkedListType() //destructor
- {
- destroyList();
- }//end destructor
- template <class type="">
- linkedListType<type>::linkedListType
- (const linkedListType<type>& otherList)
- {
- first = NULL;
- copyList(otherList);
- }//end copy constructor
- //overload the assignment operator
- template <class type="">
- const linkedListType<type>& linkedListType<type>::operator=
- (const linkedListType<type>& otherList)
- {
- if (this != &otherList) //avoid self-copy
- {
- copyList(otherList);
- }//end else
- return *this;
- }
- #endif
- </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>
- #ifndef H_UnorderedLinkedList
- #define H_UnorderedLinkedList
- #include "linkedList.h"
- using namespace std;
- template <class type="">
- class unorderedLinkedList: public linkedListType<type>
- {
- public:
- bool search(const Type& searchItem) const;
- //Function to determine whether searchItem is in the list.
- //Postcondition: Returns true if searchItem is in the
- // list, otherwise the value false is
- // returned.
- void insertFirst(const Type& newItem);
- //Function to insert newItem at the beginning of the list.
- //Postcondition: first points to the new list, newItem is
- // inserted at the beginning of the list,
- // last points to the last node in the
- // list, and count is incremented by 1.
- void insertLast(const Type& newItem);
- //Function to insert newItem at the end of the list.
- //Postcondition: first points to the new list, newItem
- // is inserted at the end of the list,
- // last points to the last node in the
- // list, and count is incremented by 1.
- void deleteNode(const Type& deleteItem);
- //Function to delete deleteItem from the list.
- //Postcondition: If found, the node containing
- // deleteItem is deleted from the list.
- // first points to the first node, last
- // points to the last node of the updated
- // list, and count is decremented by 1.
- };
- template <class type="">
- bool unorderedLinkedList<type>::
- search(const Type& searchItem) const
- {
- nodeType<type> *current; //pointer to traverse the list
- bool found = false;
- current = first; //set current to point to the first
- //node in the list
- while (current != NULL && !found) //search the list
- if (current->info == searchItem) //searchItem is found
- found = true;
- else
- current = current->link; //make current point to
- //the next node
- return found;
- }//end search
- template <class type="">
- void unorderedLinkedList<type>::insertFirst(const Type& newItem)
- {
- nodeType<type> *newNode; //pointer to create the new node
- newNode = new nodeType<type>; //create the new node
- newNode->info = newItem; //store the new item in the node
- newNode->link = this -> first; //insert newNode before first
- first = newNode; //make first point to the
- //actual first node
- count++; //increment count
- if (last == NULL) //if the list was empty, newNode is also
- //the last node in the list
- last = newNode;
- }//end insertFirst
- template <class type="">
- void unorderedLinkedList<type>::insertLast(const Type& newItem)
- {
- nodeType<type> *newNode; //pointer to create the new node
- newNode = new nodeType<type>; //create the new node
- newNode->info = newItem; //store the new item in the node
- newNode->link = NULL; //set the link field of newNode
- //to NULL
- if ( first == NULL) //if the list is empty, newNode is
- //both the first and last node
- {
- first = newNode;
- last = newNode;
- count++; //increment count
- }
- else //the list is not empty, insert newNode after last
- {
- last->link = newNode; //insert newNode after last
- last = newNode; //make last point to the actual
- //last node in the list
- count++; //increment count
- }
- }//end insertLast
- template <class type="">
- void unorderedLinkedList<type>::deleteNode(const Type& deleteItem)
- {
- nodeType<type> *current; //pointer to traverse the list
- nodeType<type> *trailCurrent; //pointer just before current
- bool found;
- if (first == NULL) //Case 1; the list is empty.
- cout << "Cannot delete from an empty list."
- << endl;
- else
- {
- if (first->info == deleteItem) //Case 2
- {
- current = first;
- first = first->link;
- count--;
- if (first == NULL) //the list has only one node
- last = NULL;
- delete current;
- }
- else //search the list for the node with the given info
- {
- found = false;
- trailCurrent = first; //set trailCurrent to point
- //to the first node
- current = first->link; //set current to point to
- //the second node
- while (current != NULL && !found)
- {
- if (current->info != deleteItem)
- {
- trailCurrent = current;
- current = current-> link;
- }
- else
- found = true;
- }//end while
- if (found) //Case 3; if found, delete the node
- {
- trailCurrent->link = current->link;
- this -> count--;
- if (last == current) //node to be deleted
- //was the last node
- last = trailCurrent; //update the value
- //of last
- delete current; //delete the node from the list
- }
- else
- cout << "The item to be deleted is not in "
- << "the list." << endl;
- }//end else
- }//end else
- }//end deleteNode
- #endif
- </type></type></type></class></type></type></type></class></type></type></type></class></type></type></class></type></class>
- //This program tests various operation of a linked list
- //34 62 21 90 66 53 88 24 10 -999
- #include <iostream>
- #include "unorderedLinkedList.h"
- using namespace std;
- int main()
- {
- unorderedLinkedList<int> list1, list2; //Line 1
- int num; //Line 2
- cout << "Line 3: Enter integers ending "
- << "with -999" << endl; //Line 3
- cin >> num; //Line 4
- while (num != -999) //Line 5
- {
- list1.insertLast(num); //Line 6
- cin >> num; //Line 7
- }
- cout << endl; //Line 8
- cout << "Line 9: list1: "; //Line 9
- list1.print(); //Line 10
- cout << endl; //Line 11
- cout << "Line 12: Length of list1: "
- << list1.length() << endl; //Line 12
- list2 = list1;
- //test the assignment operator Line 13
- cout << "Line 16: list2: "; //Line 14
- list2.print(); //Line 15
- cout << endl; //Line 16
- cout << "Line 17: Length of list2: "
- << list2.length() << endl; //Line 17
- cout << "Line 18: Enter the number to be "
- << "deleted: "; //Line 18
- cin >> num; //Line 19
- cout << endl; //Line 20
- list2.deleteNode(num); //Line 21
- cout << "Line 22: After deleting " << num
- << " list2: " << endl; //Line 22
- list2.print(); //Line 23
- cout << endl; //Line 24
- cout << "Line 25: Length of list2: "
- << list2.length() << endl; //Line 25
- cout << endl << "Line 26: Output list1 "
- << "using an iterator" << endl; //LIne 26
- linkedListIterator<int> it; //Line 27
- for (it = list1.begin(); it != list1.end();
- ++it) //Line 28
- cout << *it << " "; //Line 29
- cout << endl; //Line 30
- return 0;
- }</int></int></iostream>
错误分析: 按照标准看, 上述的错误似乎有点问题。 因为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
- #ifndef H_UnorderedLinkedList
- #define H_UnorderedLinkedList
- #include "linkedList.h"
- using namespace std;
- template <class type="">
- class unorderedLinkedList: public linkedListType<type>
- {
- public:
- bool search(const Type& searchItem) const;
- //Function to determine whether searchItem is in the list.
- //Postcondition: Returns true if searchItem is in the
- // list, otherwise the value false is
- // returned.
- void insertFirst(const Type& newItem);
- //Function to insert newItem at the beginning of the list.
- //Postcondition: first points to the new list, newItem is
- // inserted at the beginning of the list,
- // last points to the last node in the
- // list, and count is incremented by 1.
- void insertLast(const Type& newItem);
- //Function to insert newItem at the end of the list.
- //Postcondition: first points to the new list, newItem
- // is inserted at the end of the list,
- // last points to the last node in the
- // list, and count is incremented by 1.
- void deleteNode(const Type& deleteItem);
- //Function to delete deleteItem from the list.
- //Postcondition: If found, the node containing
- // deleteItem is deleted from the list.
- // first points to the first node, last
- // points to the last node of the updated
- // list, and count is decremented by 1.
- };
- template <class type="">
- bool unorderedLinkedList<type>::
- search(const Type& searchItem) const
- {
- nodeType<type> *current; //pointer to traverse the list
- bool found = false;
- current = this -> first; //set current to point to the first
- //node in the list
- while (current != NULL && !found) //search the list
- if (current->info == searchItem) //searchItem is found
- found = true;
- else
- current = current->link; //make current point to
- //the next node
- return found;
- }//end search
- template <class type="">
- void unorderedLinkedList<type>::insertFirst(const Type& newItem)
- {
- nodeType<type> *newNode; //pointer to create the new node
- newNode = new nodeType<type>; //create the new node
- newNode->info = newItem; //store the new item in the node
- newNode->link = this -> first; //insert newNode before first
- this -> first = newNode; //make first point to the
- //actual first node
- this -> count++; //increment count
- if (this -> last == NULL) //if the list was empty, newNode is also
- //the last node in the list
- this -> last = newNode;
- }//end insertFirst
- template <class type="">
- void unorderedLinkedList<type>::insertLast(const Type& newItem)
- {
- nodeType<type> *newNode; //pointer to create the new node
- newNode = new nodeType<type>; //create the new node
- newNode->info = newItem; //store the new item in the node
- newNode->link = NULL; //set the link field of newNode
- //to NULL
- if ( this -> first == NULL) //if the list is empty, newNode is
- //both the first and last node
- {
- this -> first = newNode;
- this -> last = newNode;
- this -> count++; //increment count
- }
- else //the list is not empty, insert newNode after last
- {
- this -> last->link = newNode; //insert newNode after last
- this -> last = newNode; //make last point to the actual
- //last node in the list
- this -> count++; //increment count
- }
- }//end insertLast
- template <class type="">
- void unorderedLinkedList<type>::deleteNode(const Type& deleteItem)
- {
- nodeType<type> *current; //pointer to traverse the list
- nodeType<type> *trailCurrent; //pointer just before current
- bool found;
- if (this -> first == NULL) //Case 1; the list is empty.
- cout << "Cannot delete from an empty list."
- << endl;
- else
- {
- if (this -> first->info == deleteItem) //Case 2
- {
- current = this -> first;
- this -> first = this -> first->link;
- this -> count--;
- if (this -> first == NULL) //the list has only one node
- this -> last = NULL;
- delete current;
- }
- else //search the list for the node with the given info
- {
- found = false;
- trailCurrent = this -> first; //set trailCurrent to point
- //to the first node
- current = this -> first->link; //set current to point to
- //the second node
- while (current != NULL && !found)
- {
- if (current->info != deleteItem)
- {
- trailCurrent = current;
- current = current-> link;
- }
- else
- found = true;
- }//end while
- if (found) //Case 3; if found, delete the node
- {
- trailCurrent->link = current->link;
- this -> count--;
- if (this -> last == current) //node to be deleted
- //was the last node
- this -> last = trailCurrent; //update the value
- //of last
- delete current; //delete the node from the list
- }
- else
- cout << "The item to be deleted is not in "
- << "the list." << endl;
- }//end else
- }//end else
- }//end deleteNode
- #endif
- </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 网站上得到的解答: