Clang Linker说符号不确定

Clang linker says symbols undefined

本文关键字:不确定 符号 Linker Clang      更新时间:2023-10-16

clang在我尝试编译我的自定义链接列表测试时,已经为我提供以下输出...

Scanning dependencies of target C__DataStructures
[ 33%] [ 66%] Building CXX object CMakeFiles/C__DataStructures.dir/TTLinkedList.cpp.o
Building CXX object CMakeFiles/C__DataStructures.dir/main.cpp.o
Linking CXX executable C__DataStructures
Undefined symbols for architecture x86_64:
"TTDataStructs::TTLinkedList<int>::TTLinkedList()", referenced from:
    _main in main.cpp.o
"TTDataStructs::TTLinkedList<int>::~TTLinkedList()", referenced from:
    _main in main.cpp.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [C__DataStructures] Error 1
make[1]: *** [CMakeFiles/C__DataStructures.dir/all] Error 2
make: *** [all] Error 2

我一直在试图找到我做错了什么,我所能在网上找到的只是通常是在您在.cpp文件中编写定义为constructor()而不是class :: constructor()时引起的。我认为这里并非如此。这是我的第一个C 项目,因此我可能正在做一些愚蠢的事情。这是我的Main.cpp

的代码
    #include <iostream>
    #include "TTLinkedList.h"
    using namespace std;
    using namespace TTDataStructs;
    int main() {
        TTLinkedList<int> intList;
        intList = TTLinkedList<int>();
        return 0;
    }

这是我的ttlinkedlist.h

#ifndef C__DATASTRUCTURES_TTLINKEDLISTCPP_H
#define C__DATASTRUCTURES_TTLINKEDLISTCPP_H
#include "TTNode.h"
namespace TTDataStructs {
    template<class T2>
    class TTNode;
    template<class T>
    class TTLinkedList {
    public:
        TTLinkedList();//Constructor
        ~TTLinkedList();//Destructor
        bool isEmpty(); //Checks to see if there are any nodes in the linked list
        void insertAsFirstElement(const T& data); //insert element as the first node
        void insertAsLastElement(const T& data); //insert element as the last node
        void insertAt(const T& data, int position); //insert element at a specified position
        void remove(int position); //delete at a specified position
        void removeFirstElement(); //delete the first element of the list if it exists
        void removeLastElement();  //delete the last element of the list if it exists
        void showList(); //print the list
        void clearList(); //clear the list

    private:
        TTNode<T>* head; //pointer to the first node
        TTNode<T>* createNode(const T& data,TTNode<T>* nextNode); //create a node with these specified parameters
        void freeNode(TTNode<T>* ptrToFree);
    };
}
#endif //C__DATASTRUCTURES_TTLINKEDLISTCPP_H

...和我的ttlinkedlist.cpp文件。

#include <iostream>
#include "TTLinkedList.h"
using namespace std;
namespace TTDataStructs {
    //Linked List constructor
    template<class T>
    TTLinkedList<T>::TTLinkedList(): head(nullptr) {}
    //Linked List destructor
    template<class T>
    TTLinkedList<T>::~TTLinkedList() {
        clearList();
    }
    //Returns a boolean to indicate whether or not the list has any nodes
    template<class T>
    bool TTLinkedList<T>::isEmpty() {
        if(head) {
            return true;
        }
        return false;
    }
    template <class T>
    TTNode<T>* TTLinkedList<T>::createNode(const T& data, TTNode<T>* nextNode) {
        TTNode<T>* createdNode;
        createdNode = new (nothrow) TTNode<T>(data,nextNode);
        //catch mem allocation (bad_alloc exception) errors
        if (createdNode == NULL) {
            cerr << "Memory allocation error!" << endl;
            exit(1);
        }
        return createdNode;
    }
    //Deletes a node
    template <class T>
    void TTLinkedList<T>::freeNode(TTNode<T>* ptrToFree) {
        delete ptrToFree;
    }
    //insert as the first node in the Linked List
    template  <class T>
    void TTLinkedList<T>::insertAsFirstElement(const T& data)
    {
        TTNode<T>* createdNode = createNode(data, head);
        head = createdNode;
    }
    //insert element as the last node
    template <class T>
    void TTLinkedList<T>::insertAsLastElement(const T& data) {
        TTNode<T>* createdNode = createNode(data, nullptr);
        if(head)
        {
            TTNode<T>* currentNode;
            TTNode<T>* prevNode;
            currentNode = head;
            while(currentNode) {
                prevNode = currentNode;
                currentNode = currentNode->nextNode;
            }
            prevNode->nextNode = createdNode;
        } else {
            head = createdNode;
        }
    }
    //insert element at a specified position
    //if negative position given, insert at 0. If a position larger than list length is given, insert at the end.
    template <class T>
    void TTLinkedList<T>::insertAt(const T& data, int position) {
        if(position <= 0){
            insertAsFirstElement(data);
        } else
        {
            TTNode<T>* prevNode;
            TTNode<T>* currentNode = head;
            for(int i = 0; (i != position) && (currentNode != nullptr && currentNode != NULL); ++i) {
                prevNode = currentNode;
                currentNode = currentNode->nextNode;
            }
            TTNode<T>* toInsert = createNode(data, currentNode);
            prevNode->nextNode = toInsert;
        }
    }
    //delete an element at a specified position
    //if negative position given, remove at 0. If a position larger than list length is given, insert at the end.
    //if a list's head does not point to anything does nothing
    template <class T>
    void TTLinkedList<T>::remove(int position)
    {
        if(head)
        {
            //if there is only one node or position param is less than 0, remove the first element
            if (position <= 0 || (head->nextNode == nullptr || head->nextNode == NULL)) {
                removeFirstElement();
            } else {
                TTNode<T> *prevNode = nullptr;
                TTNode<T> *currentNode = head;
                //get to position to pinch off desired node
                for (int i = 0;
                     (i != position) && (currentNode->nextNode != nullptr && currentNode->nextNode != NULL); ++i) {
                    prevNode = currentNode;
                    currentNode = currentNode->nextNode;
                }
                //pinch off the element from the linked list and dealloc its memory here
                prevNode->nextNode = currentNode->nextNode;
                freeNode(currentNode);
            }
        }
    }
    //delete the first element of the list if it exists
    template  <class T>
    void TTLinkedList<T>::removeFirstElement() {
        if (head) {
            TTNode<T>* tmpPtrHolder = head;
            head = head->nextNode;
            freeNode(tmpPtrHolder);
        }
    }
    template <class T>
    void TTLinkedList<T>::removeLastElement() {
        if(head)
        {
            //if there is only one node or position param is less than 0, remove the first element
            if (head->nextNode == nullptr || head->nextNode == NULL) {
                removeFirstElement();
            } else {
                TTNode<T> *prevNode = nullptr;
                TTNode<T> *currentNode = head;
                //get to position to pinch off desired node
                while (currentNode->nextNode != nullptr && currentNode->nextNode != NULL) {
                    prevNode = currentNode;
                    currentNode = currentNode->nextNode;
                }
                //pinch off the element from the linked list and dealloc its memory here
                prevNode->nextNode = currentNode->nextNode;
                freeNode(currentNode);
            }
        }
    }
    //clear the list
    template <class T>
    void TTLinkedList<T>::clearList() {
        while(head) {
            removeFirstElement();
        }
    }
    //print the list. Makes the assuption that T implements the << operator.
    template <class T>
    void TTLinkedList<T>::showList() {
        if (head) {
            TTNode<T> *currentNode = head;
            while(currentNode) {
                cout << currentNode->data << endl;
                if(currentNode->nextNode) {
                    cout << ", " << endl;
                }
                currentNode = currentNode->nextNode;
            }
        }
    }
}

这是我为我生成的CMAKE文件。

cmake_minimum_required(VERSION 3.2)
project(C__DataStructures)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
set(SOURCE_FILES main.cpp)
add_executable(C__DataStructures ${SOURCE_FILES} TTLinkedList.cpp TTLinkedList.h TTNode.cpp TTNode.h)

(TT是我的缩写

您的类是模板。当另一个代码需要时,根据需求实例化模板代码。因此,您不能单独编译课程(因为它是一个模板,所以没有任何编译,因此链接器报告了未定义的符号)。您必须将模板类的实现放在标题文件中。