最新文章专题视频专题问答1问答10问答100问答1000问答2000关键字专题1关键字专题50关键字专题500关键字专题1500TAG最新视频文章推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37视频文章20视频文章30视频文章40视频文章50视频文章60 视频文章70视频文章80视频文章90视频文章100视频文章120视频文章140 视频2关键字专题关键字专题tag2tag3文章专题文章专题2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章专题3
当前位置: 首页 - 科技 - 知识百科 - 正文

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

来源:动视网 责编:小采 时间:2020-11-09 07:26:48
文档

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

C++关于模板之间的继承,导致的模板子类的成员看不到(cannot:首先, 开门见山, 这个难题的解决办法是用this指针, 或者使用父类配合着scope resolution。 这个问题是我在学习linked list as an ADT , linked list 是含有纯虚函数, 所以是抽象基础类。 然后又linked list 继承出unordered lin
推荐度:
导读C++关于模板之间的继承,导致的模板子类的成员看不到(cannot:首先, 开门见山, 这个难题的解决办法是用this指针, 或者使用父类配合着scope resolution。 这个问题是我在学习linked list as an ADT , linked list 是含有纯虚函数, 所以是抽象基础类。 然后又linked list 继承出unordered lin


首先, 开门见山, 这个难题的解决办法是用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 << current->info << " ";
 current = current->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 << "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

主程序如下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 << "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 it; //Line 27

 for (it = list1.begin(); it != list1.end();
 ++it) //Line 28
 cout << *it << " "; //Line 29
 cout << endl; //Line 30

 return 0;
}

编译结果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 << "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

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




关于这个模板继承, 子类使用父类的成员是使用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

C++关于模板之间的继承,导致的模板子类的成员看不到(cannot:首先, 开门见山, 这个难题的解决办法是用this指针, 或者使用父类配合着scope resolution。 这个问题是我在学习linked list as an ADT , linked list 是含有纯虚函数, 所以是抽象基础类。 然后又linked list 继承出unordered lin
推荐度:
标签: 看不到 成员 模板
  • 热门焦点

最新推荐

猜你喜欢

热门推荐

专题
Top