簡體   English   中英

使用模板將堆棧實現為鏈接列表時出現“找不到符號”錯誤

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM