Clang链接器表示符号未定义

时间:2015-05-13 14:33:40

标签: c++ cmake

当我尝试在clion中编译自定义链表测试时,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文件中将定义写为构造函数()时引起的错误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是我的首字母缩写,这就是为什么我的课程加上他们的前缀)

1 个答案:

答案 0 :(得分:1)

你的班级是一个模板。当另一个代码需要时,模板代码按需实例化。因此,您无法单独编译类的主体(由于它是模板而没有编译任何内容,因此链接器报告未定义的符号)。您必须将模板化类的实现放到头文件中。