当我尝试在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是我的首字母缩写,这就是为什么我的课程加上他们的前缀)
答案 0 :(得分:1)
你的班级是一个模板。当另一个代码需要时,模板代码按需实例化。因此,您无法单独编译类的主体(由于它是模板而没有编译任何内容,因此链接器报告未定义的符号)。您必须将模板化类的实现放到头文件中。