首先, 开门见山, 这个难题的解决办法是用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
#include
using namespace std;
//Definition of the node
template
struct nodeType
{
Type info;
nodeType *link;
};
template
class linkedListIterator
{
public:
linkedListIterator();
//Default constructor
//Postcondition: current = NULL;
linkedListIterator(nodeType *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 operator++();
//Overload the pre-increment operator.
//Postcondition: The iterator is advanced to the next
// node.
bool operator==(const linkedListIterator & 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 & 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 *current; //pointer to point to the current
//node in the linked list
};
template
linkedListIterator ::linkedListIterator()
{
current = NULL;
}
template
linkedListIterator ::
linkedListIterator(nodeType *ptr)
{
current = ptr;
}
template
Type linkedListIterator ::operator*()
{
return current->info;
}
template
linkedListIterator linkedListIterator ::operator++()
{
current = current->link;
return *this;
}
template
bool linkedListIterator ::operator==
(const linkedListIterator & right) const
{
return (current == right.current);
}
template
bool linkedListIterator ::operator!=
(const linkedListIterator & right) const
{ return (current != right.current);
}
//***************** class linkedListType ****************
template
class linkedListType
{
public:
const linkedListType & operator=
(const linkedListType &);
//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 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 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 & 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 *first; //pointer to the first node of the list
nodeType *last; //pointer to the last node of the list
private:
void copyList(const linkedListType & otherList);
//Function to make a copy of otherList.
//Postcondition: A copy of otherList is created and
// assigned to this list.
};
template
bool linkedListType ::isEmptyList() const
{
return(first == NULL);
}
template
linkedListType ::linkedListType() //default constructor
{
first = NULL;
last = NULL;
count = 0;
}
template
void linkedListType ::destroyList()
{
nodeType *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
void linkedListType ::initializeList()
{
destroyList(); //if the list has any nodes, delete them
}
template
void linkedListType ::print() const
{
nodeType *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 info link;
}
}//end print
template
int linkedListType ::length() const
{
return count;
} //end length
template
Type linkedListType ::front() const
{
assert(first != NULL);
return first->info; //return the info of the first node
}//end front
template
Type linkedListType ::back() const
{
assert(last != NULL);
return last->info; //return the info of the last node
}//end back
template
linkedListIterator linkedListType ::begin()
{
linkedListIterator temp(first);
return temp;
}
template
linkedListIterator linkedListType ::end()
{
linkedListIterator temp(NULL);
return temp;
}
template
void linkedListType ::copyList
(const linkedListType & otherList)
{
nodeType *newNode; //pointer to create a node
nodeType *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 ; //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 ; //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
linkedListType ::~linkedListType() //destructor
{
destroyList();
}//end destructor
template
linkedListType ::linkedListType
(const linkedListType & otherList)
{
first = NULL;
copyList(otherList);
}//end copy constructor
//overload the assignment operator
template
const linkedListType & linkedListType ::operator=
(const linkedListType & otherList)
{
if (this != &otherList) //avoid self-copy
{
copyList(otherList);
}//end else
return *this;
}
#endif
unorderedLinkedList.h文件如下:
#ifndef H_UnorderedLinkedList
#define H_UnorderedLinkedList
#include "linkedList.h"
using namespace std;
template
class unorderedLinkedList: public linkedListType
{
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
bool unorderedLinkedList ::
search(const Type& searchItem) const
{
nodeType *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
void unorderedLinkedList ::insertFirst(const Type& newItem)
{
nodeType *newNode; //pointer to create the new node
newNode = new nodeType ; //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
void unorderedLinkedList ::insertLast(const Type& newItem)
{
nodeType *newNode; //pointer to create the new node
newNode = new nodeType ; //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
void unorderedLinkedList ::deleteNode(const Type& deleteItem)
{
nodeType *current; //pointer to traverse the list
nodeType *trailCurrent; //pointer just before current
bool found;
if (first == NULL) //Case 1; the list is empty.
cout 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 主程序如下main.cpp:
//This program tests various operation of a linked list
//34 62 21 90 66 53 88 24 10 -999
#include
#include "unorderedLinkedList.h"
using namespace std;
int main()
{
unorderedLinkedList list1, list2; //Line 1
int num; //Line 2
cout > num; //Line 4
while (num != -999) //Line 5
{
list1.insertLast(num); //Line 6
cin >> num; //Line 7
}
cout > num; //Line 19
cout it; //Line 27
for (it = list1.begin(); it != list1.end();
++it) //Line 28
cout 编译结果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 解决这个问题。
#ifndef H_UnorderedLinkedList
#define H_UnorderedLinkedList
#include "linkedList.h"
using namespace std;
template
class unorderedLinkedList: public linkedListType
{
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
bool unorderedLinkedList ::
search(const Type& searchItem) const
{
nodeType *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
void unorderedLinkedList ::insertFirst(const Type& newItem)
{
nodeType *newNode; //pointer to create the new node
newNode = new nodeType ; //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
void unorderedLinkedList ::insertLast(const Type& newItem)
{
nodeType *newNode; //pointer to create the new node
newNode = new nodeType ; //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
void unorderedLinkedList ::deleteNode(const Type& deleteItem)
{
nodeType *current; //pointer to traverse the list
nodeType *trailCurrent; //pointer just before current
bool found;
if (this -> first == NULL) //Case 1; the list is empty.
cout 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 编译通过, 运行结果如下:
关于这个模板继承, 子类使用父类的成员是使用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 网站上得到的解答:
查看更多关于C++关于模板之间的继承,导致的模板子类的成员看不到(cannot的详细内容...