体系结构和链接器错误的未定义符号 - 无法找出原因



我必须复制和扩展数据结构类的一些代码。它是作为 ADT 的链表模板。我遇到了一些错误,但是在花了几个小时研究它们是什么并梳理我的代码之后,我一生都无法弄清楚我错过了什么。我见过其他人发布了同样的错误,但看看他们的代码出了什么问题,我似乎没有这些问题 - 或者如果我有,我完全忽略了它。

所以这里是 .h、.cpp 和 main,后跟确切的错误:

#ifndef nodeType_h
#define nodeType_h
template<class Type>
struct nodeType
{
    Type info;
    nodeType<Type> *link;
};
#endif /* nodeType_h */
#ifndef LinkedList_h
#define LinkedList_h
#include "LinkedListIterator.h"
#include "nodeType.h"
template <class Type>
class LinkedList
{
public:
    const LinkedList<Type>& operator=(const LinkedList<Type>&);
    // Function to overload the assignment operator.
    void initializeList();
    // Function to initialize like to an empty state.
    // Precondition: A full list is passed for clearing.
    // Postcondition: first = NULL, last = NULL, count = 0;
    bool isEmptyList() const;
    // Function to determine whether or not the list is empty.
    // Precondition:
    // Postcondition: Returns true if the list is empty, false otherwise.
    void print() const;
    // Function to display data in each node.
    // Precondition: Function is called.
    // Postcondition: None.
    int length() const;
    // Function to return the number of nodes in the list.
    // Precondition:
    // Postcondition: The value of count is returned.
    void destroyList();
    // Function to delete all the nodes from the list.
    // Precondition:
    // 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 or not the searchItem is in the list.
    // Precondition:
    // Postcondition: Returns true if searchItem is in the list, false otherwise.
    virtual void insertFirst(const Type& newItem) = 0;
    // Function to insert newItem at the beginning of the list.
    // Precondition:
    // 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 beginning of the list.
    // Precondition:
    // 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.
    // Precondition:
    // 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 coint is decremented by 1.
    LinkedListIterator<Type> begin();
    // Function to return an iterator at the beginning of the linked list.
    // Precondition:
    // 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.
    // Precondition:
    // Postcondition: Returns an iterator such that current is set to NULL.
    LinkedList();
    // Default constructor initializes list to an empty state.
    // Precondition:
    // Postcondition: first = NULL, last = NULL, count = 0;
    LinkedList(const LinkedList<Type>& otherList);
    // Copy constructor.
    ~LinkedList();
    // Destructor deletes all the nodes from the list.
    // Precondition:
    // Postcondition: The list object is destoryed.
protected:
    int count; // Variable to store the number of list elements.
    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 LinkedList<Type>& otherList);
    // Function to make  copy of otherList.
    // Postcondition: A copy of otherList is created and assigned to the list.
};
#endif /* LinkedList_h */
#include "LinkedList.h"
#include "LinkedListIterator.h"
#include "nodeType.h"
#include <iostream>
template <class Type>
const LinkedList<Type>& LinkedList<Type>::operator=(const LinkedList<Type>& otherList)
{
    if(this != otherList)       // Avoid self-copy.
    {
        copyList(otherList);
    }
    return *this;
}
template <class Type>
void LinkedList<Type>::initializeList()
{
    destroyList();              // If the list has any nodes, delete them.
}
template <class Type>
bool LinkedList<Type>::isEmptyList() const
{
    return first == NULL;
}
template <class Type>
void LinkedList<Type>::print() const
{
    nodeType<Type> *current;    // Pointer to traverse the list.
    current = first;            // Point current to the first node.
    while(current != NULL)      // While there is data to print.
    {
        std::cout << current->info << " ";
        current = current->link;
    }
}
template <class Type>
int LinkedList<Type>::length() const
{
    return count;
}
template <class Type>
void LinkedList<Type>::destroyList()
{
    nodeType<Type> *temp;       // Pointer to deallocate memory occupied by the node.
    while(first != NULL)        // While there are nodes in the list.
    {
        temp = first;           // Set temp to current node.
        first = first->link;    // Advance first to the next node.
        delete temp;            // Deallocate memory occupied by temp.
    }
    last = nullptr;             // Initialize last to NULL.
    count = 0;                  // Set count to 0.
}
template <class Type>
Type LinkedList<Type>::front() const
{
    assert(first != NULL);
    return first->info;         // Return the info of the first node.
}
template <class Type>
Type LinkedList<Type>::back() const
{
    assert(last != NULL);
    return last->info;         // Return the info of the last node.
}
template <class Type>
bool LinkedList<Type>::search(const Type& searchItem) const
{
}
template <class Type>
void LinkedList<Type>::insertFirst(const Type& newItem)
{
}
template <class Type>
void LinkedList<Type>::insertLast(const Type& newItem)
{
}
template <class Type>
void LinkedList<Type>::deleteNode(const Type& deleteItem)
{
}
template <class Type>
LinkedListIterator<Type> LinkedList<Type>::begin()
{
    LinkedListIterator<Type> temp(first);
    return temp;
}
template <class Type>
LinkedListIterator<Type> LinkedList<Type>::end()
{
    LinkedListIterator<Type> temp(NULL);
    return temp;
}
template <class Type>
LinkedList<Type>::LinkedList()
{
    first = NULL;
    last = NULL;
    count = 0;
}
template <class Type>
LinkedList<Type>::LinkedList(const LinkedList<Type>& otherList)
{
    first = NULL;
    copyList(otherList);
}
template <class Type>
LinkedList<Type>::~LinkedList()
{
    destroyList();
}
template <class Type>
void LinkedList<Type>::copyList(const LinkedList<Type>& otherList)
{
    nodeType<Type> *newNode;                    // Pointer to create a node.
    nodeType<Type> *currentNode;                // Pointer to traverse the list.
    if(first != NULL)                           // If the list is not empty, empty it.
    {
        destroyList();
    }
    if(otherList.first == NULL)                 // If otherList is empty.
    {
        first = NULL;
        last = NULL;
        count = 0;
    }
    else
    {
        currentNode = otherList.first;          // currentNode points to the list to be copied.
        count = otherList.count;
        // Copy the first node.
        first = new nodeType<Type>;             // Create the node.
        first->info = currentNode->info;        // Copy the info.
        first->link = NULL;                     // Set link to NULL.
        last = first;                           // Make last point to first node.
        currentNode = currentNode->link;        // Make currentNode point to the next node.
        // Copy the rest of the list.
        while(currentNode != NULL)
        {
            newNode = new nodeType<Type>;       // Create a new node.
            newNode = currentNode->info;        // Copy the info.
            newNode->link = NULL;               // Set newNode link to NULL.    
            last->link = newNode;               // Attach newNode to end of list.
            last = newNode;                     // Make last point to last node.
            currentNode = currentNode->link;    // Make currentNode point to the next node.
        }
    }
}
#ifndef LinkedListIterator_h
#define LinkedListIterator_h
#include "nodeType.h"
template<class Type>
class LinkedListIterator
{
public:
    LinkedListIterator();
    // Default constructor.
    // Precondition:
    // Postcondition: current = NULL;
    LinkedListIterator(nodeType<Type> *ptr);
    // Constructor that accepts a nodeType object and points current to it.
    // Precondition:
    // Postcondition: current = ptr;
    Type operator*();
    // Function to overload the dereferencing operator *.
    // Precondition:
    // Postcondition: Returns the info contained in the node.
    LinkedListIterator<Type> operator++();
    // Function to overload the preincrement operator.
    // Precondition:
    // Postcondition: The iterator is advanced to the next node.
    bool operator==(const LinkedListIterator<Type>& right) const;
    // Function to overload the equality operator.
    // Precondition:
    // Postcondition: Returns true if this iterator is equal to the iterator
    //                specified by the right, false otherwise.
    bool operator!=(const LinkedListIterator<Type>& right) const;
    // Function to overload the not equal to operator.
    // Precondition:
    // Postcondition: Returns true if this iterator is not equal to the iterator
    //                specified by the right, false otherwise.
private:
    nodeType<Type> *currentNode;        // Pointer to point to the current node in the list.
};
#endif /* LinkedListIterator_h */
#include "LinkedListIterator.h"
#include <iostream>
template <class Type>
LinkedListIterator<Type>::LinkedListIterator()
{
    currentNode = NULL;
}
template <class Type>
LinkedListIterator<Type>::LinkedListIterator(nodeType<Type> *ptr)
{
    currentNode = ptr;
}
template <class Type>
Type LinkedListIterator<Type>::operator*()
{
    return currentNode->info;
}
template <class Type>
LinkedListIterator<Type> LinkedListIterator<Type>::operator++()
{
    currentNode = currentNode->link;
}
template <class Type>
bool LinkedListIterator<Type>::operator==(const LinkedListIterator<Type> &right) const
{
    return (currentNode == right.currentNode);
}
template <class Type>
bool LinkedListIterator<Type>::operator!=(const LinkedListIterator<Type> &right) const
{
    return (currentNode != right.currentNode);
}
#ifndef UnorderedLinkedList_h
#define UnorderedLinkedList_h
#include "LinkedList.h"
#include "nodeType.h"
#include <iostream>
template <class Type>
class UnorderedLinkedList: public LinkedList<Type>
{
public:
    bool search(const Type& searchItem) const;
    // Function to determine whether or not the searchItem is in the list.
    // Precondition:
    // Postcondition: Returns true if searchItem is in the list, false otherwise.
    void insertFirst(const Type& newItem);
    // Function to insert newItem at the beginning of the list.
    // Precondition:
    // 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 beginning of the list.
    // Precondition:
    // 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.
    // Precondition:
    // 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 coint is decremented by 1.
};
#endif /* UnorderedLinkedList_h */
#include <stdio.h>
#include "UnorderedLinkedList.h"
template <class Type>
bool UnorderedLinkedList<Type>::search(const Type &searchItem) const
{
    nodeType<Type> *currentNode;                // Pointer to traverse the list.
    bool found = false;
    currentNode = LinkedList<Type>::first;      // Set currentNode to point to the first node in the list.
    while(currentNode != NULL && !found)        // Search the list.
    {
        if(currentNode->info == searchItem)     // If seachItem is found.
        {
            found = true;
        }
        else
        {
            currentNode = currentNode->link;    // Makes current point to the next node.
        }
    }
}
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 = LinkedList<Type>::first;                // Insert newNode before first.
    LinkedList<Type>::first = newNode;                      // Make first point to the actual first node.
    LinkedList<Type>::count++;                              // Increment count.
    if(LinkedList<Type>::last == NULL)                     // If the list was empty, newNode is also the last node.
    {
        LinkedList<Type>::last = newNode;
    }
}
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 of newNode to NULL.
    if(LinkedList<Type>::first == NULL)                     // If the list is empty, insert newNode after last.
    {
        LinkedList<Type>::first = newNode;
        LinkedList<Type>::last = newNode;
        LinkedList<Type>::count++;                          // Increment count.
    }
    else
    {
        LinkedList<Type>::last->link = newNode;             // Insert newNode after last.
        LinkedList<Type>::last = newNode;                   // Make last point to the actual last node in the list.
        LinkedList<Type>::count++;                          // Increment count.
    }
}
template <class Type>
void UnorderedLinkedList<Type>::deleteNode(const Type &deleteItem)
{
    nodeType<Type> *currentNode;                // Pointer for traversing the list.
    nodeType<Type> *trailCurrent;               // Pointer just before current.
    bool found;
    if(LinkedList<Type>::first == NULL)
    {
        std::cout << "Cannot delete from an empty list.n";
    }
    else
    {
        if(this->first->info == deleteItem)
        {
            currentNode = LinkedList<Type>::first;
            LinkedList<Type>::first = LinkedList<Type>::first->link;
            LinkedList<Type>::count++;
            if(LinkedList<Type>::first == NULL)
            {
                LinkedList<Type>::last = NULL;
            }
            delete currentNode;
        }
        else                                    // Search the list for the node with the given info.
        {
            found = false;
            trailCurrent = LinkedList<Type>::first;         // Set trailCurrent to point to the first node.
            currentNode = LinkedList<Type>::first->link;    // Set currentNode to point to the second node.
            while(currentNode != NULL && !found)
            {
                if(currentNode->info != deleteItem)
                {
                    trailCurrent = currentNode;
                    currentNode = currentNode->link;
                }
                else
                {
                   found = true;
            }
        }
        if(found)                           // If found, delete the node.
        {
            trailCurrent->link = currentNode->link;
            LinkedList<Type>::count--;
            if(LinkedList<Type>::ast == currentNode)   // Node to be deleted was the last node.
            {
                LinkedList<Type>::last = trailCurrent;  // Update the value of last.
            }
            delete currentNode;             // Delete the node from the list.
        }
        else
        {
            std::cout << "The item to be deleted is not in the list.n";
        }
    }
}
}
#include <iostream>
#include "stdio.h"
#include "UnorderedLinkedList.h"
int main()
{
UnorderedLinkedList<int> list1, list2;
int num;
for(int i = 0; i < 10; i++)
{
    std::cout << "Enter a number: ";
    std::cin >> num;
    std::cout << std::endl;
    if(i == 0)
    {
        list1.insertFirst(num);
    }
    else
    {
        list1.insertLast(num);
    }
}
list1.print();
return 0;
}

错误:

Undefined symbols for architecture x86_64:
  "LinkedList<int>::LinkedList()", referenced from:
      UnorderedLinkedList<int>::UnorderedLinkedList() in main.o
  "LinkedList<int>::~LinkedList()", referenced from:
      UnorderedLinkedList<int>::~UnorderedLinkedList() in main.o
  "UnorderedLinkedList<int>::deleteNode(int const&)", referenced from:
      vtable for UnorderedLinkedList<int> in main.o
  "UnorderedLinkedList<int>::insertLast(int const&)", referenced from:
      _main in main.o
      vtable for UnorderedLinkedList<int> in main.o
  "UnorderedLinkedList<int>::insertFirst(int const&)", referenced from:
      _main in main.o
      vtable for UnorderedLinkedList<int> in main.o
  "LinkedList<int>::print() const", referenced from:
      _main in main.o
  "UnorderedLinkedList<int>::search(int const&) const", referenced from:
      vtable for UnorderedLinkedList<int> in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

我从教科书上复制了上面的代码,除了主要的。主要不是从教科书中复制的,尽管它也可能是。我只是想在对家庭作业进行所需的更改之前让它工作,但它没有发生。任何意见将不胜感激。谢谢。

问题解决了,尽管我仍然不知道代码出了什么问题。两位教授看了看,看不出有什么不对劲的地方,最终,我得知源代码是可用的。我下载了它并将其与我所拥有的进行了比较。它是相同的,只是它在头文件中包含了实现代码,这应该没有区别。无论如何,这不再是问题。