0

さまざまなオブジェクトを保持する Templated クラスを作成して、私にとって新しい自己記述データ構造と ptr について少し学習しようとしています。私はこの時点で立ち往生しています:

template <class T> class Linked_List
{

    struct Node
    {
        T data;
        Node* prev;
        Node* next;
        Node(T d, Node* p, Node* n) : data(d),
        prev(p), next(n) {}
    };

public:
    Linked_List();
    ~Linked_List();

    void push_back(T data);
    void push_front(T data);
    void insertAt(T data, int pos);

    T pop_back();
    T pop_front();

    int size();
    bool empty();

private:
    Node* tail;
    Node* head;
};

次のエラーが表示されます: 'Linked_List<T>::Node::data' uses undefined class 'T'。(VS2013を使用)

私は何を間違えましたか?

ありがとう


アップデート:

#include "Linked_List.h"


template<class T> Linked_List<T>::Linked_List()
{
    head = 0;
    tail = 0;
}

template<class T> Linked_List<T>::~Linked_List()
{
    {
        while (head)
        {
            Node* temp(head); //pointer to head
            head = head->next; // go to next
            delete temp; //delete the pointer
        }
    }
}

template <class T>
void Linked_List<T>::push_back(T data)
{
    //create the new Node
    tail = new Node(data, tail, NULL);
    if (tail->prev) //add to tail
        tail->prev->next = tail;
    if (empty()) // if empty its also the head
        head = tail;
}

template <class T>
void Linked_List<T>::push_front(T data)
{
    head = new Node(data, 0, tail);
    if (head->next)
        head->next->prev = head;
    if (empty())
        tail = head;
}

template <class T>
bool Linked_List<T>::empty()
{
    return (!head || !tail);
}

template <class T>
T Linked_List<T>::pop_back()
{
    if (empty())
        throw("Linked_list is empty!");
    //pointer to the element we want to have
    Node* temp(tail);
    //set the tail to prev
    tail = tail->prev;
    //get the data
    T data = temp->data;

    //the prev does not have a next now
    if (tail)
        tail->next = 0;
    else
        head = 0;

    //delete the node which held our data
    delete temp;
    //return the data
    return data;
}

template <class T>
T Linked_List<T>::pop_front()
{
    if (empty())
        throw("Linked_list is empty!");
    //pointer to the element we want to have
    Node* temp(head);
    //set the tail to prev
    head = head->next;
    //get the data
    T data = temp->data;

    //the prev does not have a next now
    if (head)
        head->prev = 0;
    else
        tail = 0;

    //delete the node which held our data
    delete temp;
    //return the data
    return data;
}

このように単純に使用しようとしている場合の新しいスタックトレース

int main(){
    Linked_List<int> list;
    for (int i = 0; i < 20; i++)
    {
        list.push_back(i);
    }

    for (int j = 0; j < 20; j++)
    {
        cout <<  list.pop_back() << endl;
    }
}

エラー:

 Error  1   error LNK2019: unresolved external symbol "public: __thiscall Linked_List<int>::Linked_List<int>(void)" (??0?$Linked_List@H@@QAE@XZ) referenced in function _main   C:\Users\...\Documents\Visual Studio 2013\Projects\Double_Linked_List\Double_Linked_List\main.obj   Double_Linked_List
    Error   2   error LNK2019: unresolved external symbol "public: __thiscall Linked_List<int>::~Linked_List<int>(void)" (??1?$Linked_List@H@@QAE@XZ) referenced in function _main  C:\Users\...\Documents\Visual Studio 2013\Projects\Double_Linked_List\Double_Linked_List\main.obj   Double_Linked_List
    Error   3   error LNK2019: unresolved external symbol "public: void __thiscall Linked_List<int>::push_back(int)" (?push_back@?$Linked_List@H@@QAEXH@Z) referenced in function _main C:\Users\...\Documents\Visual Studio 2013\Projects\Double_Linked_List\Double_Linked_List\main.obj   Double_Linked_List
    Error   4   error LNK2019: unresolved external symbol "public: int __thiscall Linked_List<int>::pop_back(void)" (?pop_back@?$Linked_List@H@@QAEHXZ) referenced in function _main    C:\Users\...\Documents\Visual Studio 2013\Projects\Double_Linked_List\Double_Linked_List\main.obj   Double_Linked_List
    Error   5   1   error LNK1120: 4 unresolved externals   C:\Users\...\Documents\Visual Studio 2013\Projects\Double_Linked_List\Debug\Double_Linked_List.exe  1   Double_Linked_List
4

2 に答える 2

3

リンカーは非常に明確です。これらのメソッドの定義がありません。コンパイラは Linked_List クラスの宣言を確認するため文句を言いませんが、テンプレートを扱う場合はそれだけでは十分ではありません。

テンプレートのインスタンス化を成功させるには、すべてのテンプレート定義が表示される必要があります。テンプレート クラスのメソッドを cpp ファイルに実装したため (通常はヘッダーまたは impl ファイルで実装します)、テンプレートがインスタンス化される場所にそのファイルを含める必要があります。あなたの特定の例では、 main.cpp で:

#include <iostream>
#include "Linked_List.cpp"   // !!!


int main(){
    Linked_List<int> list;
    for (int i = 0; i < 20; i++)
    {
        list.push_back(i);
    }

    for (int j = 0; j < 20; j++)
    {
        std::cout <<  list.pop_back() << std::endl;
    }
}

埋め込みファイルをインクルードし、コンパイラに暗黙的にテンプレートをインスタンス化させる代わりに、ソース ファイルで明示的に行うことができます。この場合、次の行を Linked_List.cpp の最後に追加します。

template class Linked_List<int>;

ただし、その場合、別のテンプレート引数 (int 以外) を使用してオブジェクトを作成することはできません。


3 番目のオプションは、最初のオプションのバリエーションです。ヘッダーの最後にソース ファイルをインクルードします。

ヘッダ

// header.hpp
#ifndef HEADER_HPP
#define HEADER_HPP

template< typename T >
struct A
{
    void foo();
};

#include "source.impl"

#endif

ソース

// source.impl

#include "header.hpp"

template< typename T >
void A::foo()
{
}

主要

// main.cpp

#include "header.hpp"

int main()
{
  A<int> a;
  a.foo();
}
于 2013-11-12T21:09:28.627 に答える
0

通常の非テンプレート クラスの場合と同様に、テンプレート クラスの定義とそのメソッドの実装を 2 つのファイルに配置したと思います。そして、リンクされたリストを定義するヘッダー ファイルを main.cpp に含めるだけです。

これができない理由については、このスレッドを参照してください

テンプレートをヘッダー ファイルにしか実装できないのはなぜですか?

于 2013-11-16T00:43:27.970 に答える