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

时间:2017-10-14 18:09:04

标签: linker-errors undefined-symbol

我必须复制并扩展数据结构类的一些代码。它是作为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)

我从教科书右侧复制了上面的代码。主要没有从教科书中复制,尽管它可能也是如此。我只是想在完成家庭作业所需的更改之前让它工作,但它没有发生。任何意见都将非常感激。谢谢。

1 个答案:

答案 0 :(得分:0)

问题解决了,虽然我还不知道代码有什么问题。两位教授看着它,看不出有什么不对,最后,我了解到源代码可用。我下载并将其与我所拥有的相比较。它是相同的,只是它包含头文件中的实现代码,这应该没有区别。无论如何,它不再是一个问题。