[英]Getting “symbols not found” errors implementing a Stack as Linked List using templates
我正在嘗試使用鏈接列表創建堆棧。 我已經可以使用整數了,但是現在我想為其實現模板。 編譯之前沒有檢測到錯誤,但是運行后出現以下錯誤:
*體系結構x86_84的未定義符號:“ Stack :: printStack()”,引用自:main.o中的_main
“ Stack :: pop()”,引用自:main.o中的_main
“ Stack :: push(int)”,引用自:main.o中的_main
“ Stack ::〜Stack()”,引用自:main.o中的_main
ld:找不到架構x86_64的符號clang:錯誤:鏈接器命令失敗,退出代碼為1(使用-v查看調用)*
我認為麻煩來自必須定義兩個模板,一個在Stack.h文件中,一個在我的LinkedList.h文件中。 在我的Stack.h文件中,我需要調用Node,如果不包含模板參數就不能調用Node,並且如果沒有我包含另一個模板定義,Stack.h將無法識別模板參數。 現在,在某些情況下,我僅使用'T'而不是Node,但是我已經嘗試了兩種方法。 我覺得我已經嘗試了一切,但我根本不知道我的錯誤在哪里。 這時我真的只是為了概念證明,這就是為什么我沒有為Stack添加副本構造函數或其他功能的原因。 我的代碼如下。
LinkedList.h
#ifndef Linked_List__Stack_LinkedList_h
#define Linked_List__Stack_LinkedList_h
template<class T>
struct Node {
public:
Node(Node *n, T data) : next(n), data(data) {}
Node *getNext() const { return next; }
T value() const { return data; }
private:
Node* next;
T data;
};
#endif
堆棧
#ifndef __Linked_List__Stack__Stack__
#define __Linked_List__Stack__Stack__
#include "LinkedList.h"
#include <stdio.h>
#include <iostream>
using namespace std;
template <class T>
class Stack {
public:
Stack() : head(NULL), tail(NULL) {};
~Stack();
void push(T data);
T pop();
void printStack();
private:
Node<T> *head;
Node<T> *tail;
};
#endif /* defined(__Linked_List__Stack__Stack__) */
Stack.cpp
#include "Stack.h"
template <class T>
Stack<T>::~Stack() {
while (head) {
Node<T>* temp = head->getNext();
delete head;
head = temp;
}
head = tail = NULL;
}
template <class T>
void Stack<T>::push(T data) {
Node<T>* node = new Node<T>(head, data);
head = node;
if (head->getNext() == NULL )
tail = head;
}
template <class T>
T Stack<T>::pop() {
Node<T> *top = head;
T data;
if(head == NULL)
throw; //StackError(E_EMPTY);
data = head->value();
head = head->getNext();
delete top;
return data;
}
template <class T>
void Stack<T>::printStack() {
Node<T> *current = head;
while (current != tail) {
cout << current->value() << ", ";
current = current->getNext();
}
cout << current->value() << endl;
}
main.cpp
#include "Stack.h"
#include <iostream>
#include <stdexcept>
int main(int argc, const char * argv[]) {
Stack<int> *myIntStack = new Stack<int>();
myIntStack->push(10);
myIntStack->printStack();
myIntStack->pop();
myIntStack->printStack();
delete myIntStack;
return 0;
}
幾乎沒有流行的編譯器允許您將模板定義作為獨立的編譯單元放入cpp文件中(因此,鏈接器錯誤)。
簡而言之,只需將Stack.cpp的內容移動到Stack.h中(而不必理會您的Stack.cpp),那么一切都會正常進行。
我喜歡使用的另一種方式(很早……十年前,當我仍在編寫C ++的工作時)是將模板源“包括”在標題中,例如:
oo
#ifndef FOO_H__
#define FOO_H__
TEMPLATE_DECL template <class T> Foo {
....
};
#ifndef SUPPORT_TEMPLATE_EXPORT
#include "Foo.tmpl" // include it if you CANNOT compile it as separate compilation unit
#endif
#endif //ifndef FOO_H__
Foo.tmpl (我使用另一個擴展名使其與.cpp不同)
#ifdef SUPPORT_TEMPLATE_EXPORT
#include "Foo.h" // only include if you can compile it as separate compilation unit
#endif
// template definition
TEMPLATE_DEF Foo<T>::bar() {....}
當然,您需要注意預處理器和編譯器的設置,但這應該很簡單。 而且,C ++ 0x不推薦使用模板導出,如果您不關心在較早的編譯器(例如Comenu)中使用此功能,則可以進一步簡化此方法。
題外話:避免在標題中使用名稱空間(或實際上的任何using子句)。 這將導致名稱空間污染。
正如Adrian指出的那樣,編譯器需要在實例化時將所有模板實現都可用,並且我同意他的建議,即只需將實現移入Stack.h
。
但是,如果你想保持接口與實現分離自己的目的,你可以#include "Stack.cpp"
在底部Stack.h
(和刪除#include "Stack.h"
從Stack.cpp
)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.