2012-03-12 11 views
1

私はいくつかのリンクリストを前に作っていますが、概念はすべて私にとって意味がありますが、プロジェクトではテンプレートをC++で作成しなければなりません。私はいくつかの問題を抱えています。助けてください。私はそのような単純なことにあまりにも多くの時間を費やしてきました。C++テンプレートリンクリスト問題

私は既にリストクラスのいくつかを持っていますが、問題はここにあります。私はテストケースには3つのノードを作成し、私は正常に動作

node1.getNext().show(); 

を呼び出す場合、それらすべてをリンクアップが、私

node1.getNext().getNext().show(); 

私はセグメンテーションフォルトを取得する場合(コアダンプ)とき。ここで何が間違っていますか?私はgetNext()とgetPrev()の戻り値のポインタを変更することを試みました。私はこの質問をするのは馬鹿だと感じるが、重大な問題を抱えている。私のノードクラスは下にあり、segfaultを与えるサンプルテストケースが続きます。

Node.h:

template <class T> class Node 
{ 
public: 
    Node(); 
    Node(T value); 
    void setPrev(Node<T> node); 
    void setValue(T value); 
    void setNext(Node<T> node); 
    Node<T> getPrev(); 
    T getValue(); 
    Node<T> getNext(); 
    void show(); 
    ~Node() { } 

private: 
    Node<T> *prev; 
    Node<T> *next; 
    T value; 
}; 

//default construct                                      
template <class T> Node<T>::Node() { 
    this->prev = NULL; 
    this->value = NULL; 
    this->next = NULL; 
}; 

//overloaded construct                                     
template <class T> Node<T>::Node(T value) { 
    this->prev = NULL; 
    this->value = value; 
    this->next = NULL; 
} 

template <class T> void Node<T>::setPrev(Node<T> node) { 
    this->prev = &node; 
} 

template <class T> void Node<T>::setValue(T value) { 
    this->value = value; 
} 

template <class T> void Node<T>::setNext(Node<T> node) { 
    this->next = &node; 
} 

template <class T> Node<T> Node<T>::getPrev() { 
    return this->prev; 
} 

template <class T> T Node<T>::getValue() { 
    return this->value; 
} 

template <class T> Node<T> Node<T>::getNext() { 
    return this->next; 
} 

template <class T> 
void Node<T>::show() { 
    cout << value << endl; 
} 

テストケース:

int main(int argc, char **argv) { 

    typedef Node<int> IntNode; 

    IntNode head(NULL); 
    IntNode node1(23); 
    IntNode node2(45); 
    IntNode node3(77); 
    IntNode tail(NULL); 
    node1.setPrev(head); 
    node1.setNext(node2); 
    node2.setPrev(node1); 
    node2.setNext(node3); 
    node3.setPrev(node2); 
    node3.setNext(tail); 

    node1.show(); 
    node2.show(); 
    node3.show(); 

    cout << node1.getNext().getValue() << endl; 
    cout << node1.getNext().getNext().getValue() << endl; 
} 
+1

学習プロジェクトとして 'std :: list'を再実装していますか? –

+0

の代わりにsetPrev/setNextを使用すると、appendを実装して、内部でポインタをリンクするだけで済みます。さもなければクラスのモチベーションであるデータ隠蔽は効果がなく、外で扱われる 'ハード'なロジックです。 – CapelliC

答えて

4

値ではなく参照によって値を渡す必要があります。

が実行されると、setNext()はで定義する変数ではなく、node1のコピーをスタックに取得します。 setNext()が終了すると、nextに格納されているアドレスは無効になります。

は手始めに、関数を再定義setPrevとsetNext

template <class T> void Node<T>::setPrev(Node<T> &node) { 
    this->prev = &node; 
} 

template <class T> void Node<T>::setNext(Node<T> &node) { 
    this->next = &node; 
} 

として、それはあなたの即時のセグメンテーションフォルトを修正します。しかし、実際にはコードの設計や、リファレンスや値で渡したときに何が起こるのか、これを正しく書いて、それ以上の問題を避けるためにもっと考える必要があります。

+0

ありがとうございます。私が言ったように、私は数回前にC++を使用しただけなので、まだポインタに慣れていませんが、それに取り組んでいます。再度、感謝します! –

2

あなたはポインタとしてあなたの次/前のメンバーを格納する必要があります。前のノードと次のノードを設定するときは、値でパラメータを取得してコピーします。

これは、node1.getNext().getNext().getValue()の2番目の.getNext()までステップスルーすると、ぶら下がりポインタが発生するため、コードが失敗していることを意味します。

ノードを手動で追加するのは面倒です。std::listのような方法は、所有するコレクションへのポインタをbeginendにすることです。新しいノードがリストの前または後ろにプッシュされると、コレクションはノードを作成し、値を格納し、次のノードおよび/またはトラバーサルの準備が整ったポインタをリンクします。

1

大きな問題は、あなたのsetNextsetPrev関数は値によってそれらのパラメータを取るということですので、あなたは、あなたがメインで宣言したノードのコピーを取得します。

これを続行したい場合は、これらのパラメータを参照またはポインタで渡します。ポインタを渡すことはおそらくより意味的な意味を持ち、この種の偶発的な間違いを防ぐでしょう。