模板类函数的未定义错误
Posted
技术标签:
【中文标题】模板类函数的未定义错误【英文标题】:undefined error to template class function 【发布时间】:2021-12-20 00:46:09 【问题描述】:我正在尝试实现一个类模板双链表。我曾经在这里上课 DoublyLinkde List 和 Double Node。并在此处实现了 inserts() 和显示功能。 谁能帮我成功插入和显示操作。例如我想使用插入功能插入数据并希望使用显示功能看到它。
下面是代码:我把这段代码写在final.cpp文件中
template <class ItemType> //Reminder this is a template class, implement the .cpp accordingly
class DoubleNode
public:
DoubleNode();
//default constructor, sets next_ and prev_ to nullptr
DoubleNode(const ItemType &anItem, DoubleNode<ItemType> *nextNodePtr = nullptr, DoubleNode<ItemType> *previousNodePtr = nullptr); //Parameterized Constructor, sets item_ to anItem, next_ to nextNodePtr, prev_ to previousNodePtr
void setItem(const ItemType &anItem)
item_=anItem;
void setPrevious(DoubleNode<ItemType> *previousNodePtr)
next_= previousNodePtr;
void setNext(DoubleNode<ItemType> *nextNodePtr)
prev_=nextNodePtr;
ItemType getItem() const
return item_;
DoubleNode<ItemType> *getNext() const
return next_;
DoubleNode<ItemType> *getPrevious() const
return prev_;
private:
ItemType item_; //actual content of your node
DoubleNode<ItemType> *next_; //pointer to the node that is after this node
DoubleNode<ItemType> *prev_; //pointer to the node that is before this node
;
template <class ItemType>
class DoublyLinkedList
public:
// DoublyLinkedList(); //default constructor, sets headPtr_ to null and itemCount_ to 0
/*
Copy constructor that will make an exact copy of the list parameter, aList.
This will make a deep copy of the list in the given parameter.
You must iterate through the callee list parameter and insert nodes from aList into the caller list (the current one that isn't the parameter)
*/
// DoublyLinkedList(const DoublyLinkedList &aList);
// ~DoublyLinkedList(); //destructor that calls the clear function
int getSize()
return itemCount_;
//return itemCount_
/* *
* Description: finds the node at parameter pos
* Pre: pos is a valid place in the list, otherwise nullptr will be returned
* Post: returns a pointer to the node at pos
* */
DoubleNode <ItemType> *getAtPos(const int &pos) const
DoubleNode<ItemType>* curPtr=headPtr_;
for(int skip=1; skip<pos; skip++)
curPtr=curPtr->getNext();
return curPtr;
DoubleNode<ItemType> *getHeadPtr() const
return headPtr_;
//return *headPtr_
/* *
* Description: inserts parameter item in caller list at parameter position
*IMPORTANT: Position 1 is the first position, not 0
* Pre: position is a valid place within the list, otherwise false will be returned
* Post: returns true if the item has been inserted in the caller list
* Handles edge case of an invalid position parameter
* Case: Inserting into head of the list
* Case: Inserting into rear of the list
* Case: Inserting into a position that is not an extremity
* */
bool inserts(const ItemType &item, const int &position = 1)
bool ableToInsert=(position>=1)&&(position<=itemCount_+1);
if(ableToInsert)
DoubleNode<ItemType>* newNodePtr=new DoubleNode<ItemType>(item);
if(position==1)
newNodePtr->setNext(headPtr_);
headPtr_=newNodePtr;
else if(position==2)
DoubleNode<ItemType>* prevPtr=getAtPos(position-1);
newNodePtr->setNext(prevPtr->getNext());
prevPtr->setNext(newNodePtr);
else
DoubleNode<ItemType>* headPtr_=getHeadPtr();
DoubleNode<ItemType>* node = new DoubleNode<ItemType>[1];
// cout<<"test 31"<<endl;
node->setItem(item);
if(headPtr_ == nullptr)
// cout<<"test 1"<<endl;
headPtr_ = node;
// cout<<"new node added(firstnode) !"<<endl;
return true;
DoubleNode<ItemType>* temp = headPtr_;
DoubleNode<ItemType>* prev_;
// cout<<"test 1 "<<temp->next_<<endl;
while(temp->getNext() != nullptr)
//cout<<"test NULL 1"<<endl;
prev_ = temp;
temp = temp->getNext();
temp->setNext(node);
temp->setPrevious(prev_);
//cout<<"new node added at back!"<<endl;
itemCount_++;
return ableToInsert;
/* *
* Description: removes node at parameter position
*IMPORTANT: Position 1 is the first position, not 0
* Pre: position is a valid place within the list, otherwise false will be returned
* Post: returns true if the item at position has been removed from the caller list
* Handles edge case of invalid position parameter
* Case: removing only node in list
* Case: removing from the end
* Case: removing from the beginning
* Case: removing from a position that is not an extremity
* */
// bool remove(const int &position);
// bool isEmpty() const; //returns true if itemCount_ is 0
/* *
* Description: removes all items from the caller list
* Traverse through the linked list and delete each individual node
* Post: no nodes remain in the list and itemCount_ is at 0
* */
// void clear();
//Iteratively outputs the contents of the caller list on the console
//Example "A B C D E"
//Note how theres no space at the end
void display() const
// cout<<"linked list is empty"<<endl;
DoubleNode <ItemType>*headPtr_=getHeadPtr();
if(headPtr_ == nullptr)
// cout<<"linked list is empty"<<endl;
return;
// cout<<endl<<"----link list items------"<<endl;
DoubleNode<ItemType>* temp = headPtr_;
while(temp != nullptr)
// cout<<temp->item_<<" ooo| ";
temp = temp->getNext();
// cout<<endl<<"--------------------------"<<endl;
//Iteratively outputs the contents of the caller list backwards on the console
//Example if we had A B C D E we would instead display "E D C B A"
// void displayBackwards() const;
// Reverses the list such that if my list was A B C D it will now be D C B A
// Remember to change both previous and next pointers
// Will be tested with both display and displayBackwards, make sure you have those working
// void invert();
private:
DoubleNode<ItemType> *headPtr_; //points to the first item in the linked list
int itemCount_; //lists how many items are currently in the list
;
int main()
DoublyLinkedList<int> dl;
dl.inserts(4,3);
dl.display();
【问题讨论】:
请打破有问题的部分并创建一个minimal reproducible example。然后详细描述问题。您期望的结果是什么?您的实施会产生什么结果?DoubleNode
构造函数没有被定义,只是被删除了。 setPrevious
设置next_
和setNext
设置prev_
。
@kiner_shah 你能写下代码吗?因为我听不懂你说什么
@MirRahat, DoubleNode
构造函数刚刚声明(它们以分号;
结尾),它们各自的函数体在哪里?并查看您的 setPrevious
和 setNext
函数。
@kiner_shah 你能告诉我 setPrevious 和 setNext 函数吗?我的意思是我必须做什么?
【参考方案1】:
请查看注释// CHANGE HERE
的代码行和代码块。
变更摘要:
-
为
DoubleNode
的构造函数添加了定义。
更改了setPrevious
和setNext
,以便正确设置next_
和prev_
。
为DoublyLinkedList
添加了一个构造函数和一个空的析构函数(以后可以填充)。
更改了inserts
的逻辑。
稍微更改了display
函数。
更改了main
函数。请注意,inserts
返回 bool
,但您没有检查返回值。
P。 S. 非常仔细地检查修改后的代码,并尝试了解进行了哪些更改。此外,当某些东西不起作用时,您必须检查逻辑,使用调试器或简单的打印语句调试代码并修复任何错误。
#include <iostream>
template <class ItemType> //Reminder this is a template class, implement the .cpp accordingly
class DoubleNode
public:
//default constructor, sets next_ and prev_ to nullptr
// CHANGE HERE
DoubleNode() : next_(nullptr), prev_(nullptr)
//Parameterized Constructor, sets item_ to anItem, next_ to nextNodePtr, prev_ to previousNodePtr
// CHANGE HERE
DoubleNode(const ItemType &anItem, DoubleNode<ItemType> *nextNodePtr = nullptr, DoubleNode<ItemType> *previousNodePtr = nullptr)
: next_(nextNodePtr), prev_(previousNodePtr), item_(anItem)
void setItem(const ItemType &anItem)
item_=anItem;
void setPrevious(DoubleNode<ItemType> *previousNodePtr)
// CHANGE HERE
prev_ = previousNodePtr;
void setNext(DoubleNode<ItemType> *nextNodePtr)
// CHANGE HERE
next_ = nextNodePtr;
ItemType getItem() const
return item_;
DoubleNode<ItemType> *getNext() const
return next_;
DoubleNode<ItemType> *getPrevious() const
return prev_;
private:
ItemType item_; //actual content of your node
DoubleNode<ItemType> *next_; //pointer to the node that is after this node
DoubleNode<ItemType> *prev_; //pointer to the node that is before this node
;
template <class ItemType>
class DoublyLinkedList
public:
//default constructor, sets headPtr_ to null and itemCount_ to 0
// CHANGE HERE
DoublyLinkedList() : headPtr_(nullptr), itemCount_(0)
/*
Copy constructor that will make an exact copy of the list parameter, aList.
This will make a deep copy of the list in the given parameter.
You must iterate through the callee list parameter and insert nodes from aList into the caller list (the current one that isn't the parameter)
*/
// DoublyLinkedList(const DoublyLinkedList &aList);
//destructor that calls the clear function
// CHANGE HERE
~DoublyLinkedList()
int getSize()
return itemCount_;
/* *
* Description: finds the node at parameter pos
* Pre: pos is a valid place in the list, otherwise nullptr will be returned
* Post: returns a pointer to the node at pos
* */
DoubleNode <ItemType> *getAtPos(const int &pos) const
DoubleNode<ItemType>* curPtr = headPtr_;
for (int skip = 1; curPtr != nullptr && skip < pos; skip++)
curPtr = curPtr->getNext();
return curPtr;
DoubleNode<ItemType> *getHeadPtr() const
return headPtr_;
/* *
* Description: inserts parameter item in caller list at parameter position
*IMPORTANT: Position 1 is the first position, not 0
* Pre: position is a valid place within the list, otherwise false will be returned
* Post: returns true if the item has been inserted in the caller list
* Handles edge case of an invalid position parameter
* Case: Inserting into head of the list
* Case: Inserting into rear of the list
* Case: Inserting into a position that is not an extremity
* */
bool inserts(const ItemType &item, const int &position = 1)
bool ableToInsert = (position >= 1) && (position <= itemCount_ + 1);
if (ableToInsert)
DoubleNode<ItemType>* newNodePtr = new DoubleNode<ItemType>(item);
if (position == 1)
//newNodePtr->setNext(headPtr_); // CHANGE HERE
headPtr_ = newNodePtr;
else // CHANGE HERE
if (headPtr_ == nullptr)
std::cout << "ERROR: cannot insert at position " << position << ", head is nullptr\n";
return false;
DoubleNode<ItemType>* prevPtr = getAtPos(position - 1);
// CHANGE HERE
DoubleNode<ItemType>* prevNextPtr = prevPtr->getNext();
prevPtr->setNext(newNodePtr);
newNodePtr->setPrevious(prevPtr);
newNodePtr->setNext(prevNextPtr);
if (prevNextPtr)
prevNextPtr->setPrevious(newNodePtr);
// CHANGE HERE
/*else
DoubleNode<ItemType>* headPtr_ = getHeadPtr();
// CHANGE HERE
DoubleNode<ItemType>* node = new DoubleNode<ItemType>(item);
// CHANGE HERE
if (headPtr_ == nullptr)
std::cout << "ERROR: cannot insert at position " << position << ", head is nullptr\n";
return false;
DoubleNode<ItemType>* prevNode = getAtPos(position - 1);
if(headPtr_ == nullptr)
// cout<<"test 1"<<endl;
headPtr_ = node;
// cout<<"new node added(firstnode) !"<<endl;
return true;
DoubleNode<ItemType>* temp = headPtr_;
DoubleNode<ItemType>* prev_;
// cout<<"test 1 "<<temp->next_<<endl;
while(temp->getNext() != nullptr)
//cout<<"test NULL 1"<<endl;
prev_ = temp;
temp = temp->getNext();
temp->setNext(node);
temp->setPrevious(prev_);
//cout<<"new node added at back!"<<endl;
*/
itemCount_++;
return ableToInsert;
/* *
* Description: removes node at parameter position
*IMPORTANT: Position 1 is the first position, not 0
* Pre: position is a valid place within the list, otherwise false will be returned
* Post: returns true if the item at position has been removed from the caller list
* Handles edge case of invalid position parameter
* Case: removing only node in list
* Case: removing from the end
* Case: removing from the beginning
* Case: removing from a position that is not an extremity
* */
// bool remove(const int &position);
// bool isEmpty() const; //returns true if itemCount_ is 0
/* *
* Description: removes all items from the caller list
* Traverse through the linked list and delete each individual node
* Post: no nodes remain in the list and itemCount_ is at 0
* */
// void clear();
//Iteratively outputs the contents of the caller list on the console
//Example "A B C D E"
//Note how theres no space at the end
// CHANGE HERE
void display() const
// cout<<"linked list is empty"<<endl;
DoubleNode <ItemType>*headPtr_=getHeadPtr();
if(headPtr_ == nullptr)
std::cout << "linked list is empty" << std::endl;
return;
// cout<<endl<<"----link list items------"<<endl;
DoubleNode<ItemType>* temp = headPtr_;
while (temp != nullptr)
std::cout << temp->getItem() << " | ";
temp = temp->getNext();
std::cout << std::endl << "--------------------------" << std::endl;
//Iteratively outputs the contents of the caller list backwards on the console
//Example if we had A B C D E we would instead display "E D C B A"
// void displayBackwards() const;
// Reverses the list such that if my list was A B C D it will now be D C B A
// Remember to change both previous and next pointers
// Will be tested with both display and displayBackwards, make sure you have those working
// void invert();
private:
DoubleNode<ItemType> *headPtr_; //points to the first item in the linked list
int itemCount_; //lists how many items are currently in the list
;
int main()
DoublyLinkedList<int> dl;
// CHANGE HERE
bool ret = dl.inserts(4, 1);
ret = ret && dl.inserts(5, 2);
ret = ret && dl.inserts(6, 3);
ret = ret && dl.inserts(7, 4);
ret = ret && dl.inserts(8, 2);
ret = ret && dl.inserts(9, 4);
if (!ret)
std::cout << "Insert failed\n";
return 1;
dl.display();
【讨论】:
以上是关于模板类函数的未定义错误的主要内容,如果未能解决你的问题,请参考以下文章