2011-06-28 16 views
1

C++で一般的なリンクリストを作成する方法については、かなり簡単な質問で長時間苦労しています。リストには複数のタイプの構造体を含めることができるはずですが、各リストには1つのタイプの構造体しか含まれません。この問題は、getNode()関数を実装したいときに発生します。なぜなら、戻すべき構造体を指定する必要があるからです。構造体をクラスに置き換えようとしましたが、getNode関数は他のすべてのクラスによって継承される基本クラスを返しますが、コンパイラはgetNode関数が何も返さないようにするので、トリックは行いません。ベースクラス。C++での一般的なリンクリスト

だからここにいくつかのコードスニペットです:

typedef struct struct1 
{ 
    int param1; 
(...) 
} struct1; 

typedef struct struct2 
{ 
    double param1; 
(...) 
} struct2; 


typedef struct node 
{ 
    struct1 data; 
    node* link; 
} node; 

class LinkedList 
{ 
public: 
    node *first; 
    int nbrOfNodes; 
    LinkedList(); 
    void addNode(struct1); 
    struct1 getNode(); 
    bool isEmpty(); 
}; 

LinkedList::LinkedList() 
{ 
    first = NULL; 
    nbrOfNodes = 0; 
} 

void LinkedList::addNode(struct1 newData) 
{ 
    if (nbrOfNodes == 0) 
    { 
     first = new node; 
     first->data = newData; 
    } 
    else 
    { 
     node *it = first; 
     for (int i = 0; i < nbrOfNodes; i++) 
     { 
      it = it->link; 
     } 
     node *newNode = new node; 
     newNode->data = newData; 
     it->link = newNode; 
    } 
    nbrOfNodes++; 
} 

bool LinkedList::isEmpty() 
{ 
    return !nbrOfNodes; 
} 

struct1 LinkedList::getNode() 
{ 
    param1 returnData = first->data; 
    node* deleteNode = first; 
    nbrOfNodes--; 
    if (nbrOfNodes) 
     first = deleteNode->link; 
    delete deleteNode; 
    return returnData; 
} 

だから、一つの文章に入れての質問は、以下の通りである:それはまたstruct2のために使用することができるように、私は上記のリンクリストクラスを調整するにはどうすればよいです、 struct2オブジェクト用の新しいほぼ同じリストクラスを作成する必要はありませんか?上で述べたように、LinkedListの各インスタンスは、struct1またはstruct2のどちらか一方のみを扱います。 ヒントやヘルプに感謝します

+0

ノード・ポインタを無効にする*ノード・ポインタを無効にする* - それらを取り出したコードがそれらを知っている限り、特定の型を持つ必要はありません。ただキャストできます。 – Tim

+0

テンプレート、テンプレート、テンプレート.. http://en.wikipedia.org/wiki/Template_metaprogramming –

+0

可能な複製:http://stackoverflow.com/questions/4705714/c-generic-linked-list – kzh

答えて

10

すでにC++で利用可能な汎用リンクリストがあります。std::list。それは間違いなくより効率的な&あなたの使用に十分なはずです。

あなたはまだ独自のジェネリックリンクリスト を作成したい場合は、templatesの使用を検討し、リンクリストのテンプレートimplmentationを作成する必要があります。

テンプレートでは使用できない場所では、データノードはvoid*ポインタの形式で格納されます。 voidポインタが任意の汎用データ型を指すことができるという事実を利用しています。そのアプローチも考慮する必要があります。

+0

ありがとう!明らかにstd :: listオプションは私の問題を非常に瞬時に解決しましたが、将来のニーズのためにテンプレートを見ていきます。 – itsaboy

0

STL sourceは、学習するコードです。

また、どちらが任意の一般的なクラスを作ることができると理解されるべきであるtemplatesを、使用https://github.com/simonask/ftl/blob/master/list.hpp

試みることができます。

+0

...真剣に?テンプレートを認識していないと思われる人にSTLソースを見てみることをお勧めします。 – Nim

+0

はい、テンプレートを習得する必要がありますが、一方を正しい方向に向けるとコーダーにとって有益です。あなたの解説に感謝します。 – kzh

1

基本的なテンペルは簡単です。

クラスをテンプレート型の変数でテンプレートとして宣言するだけです。
ここでは、宣言型を汎用的にするために、クラス内で明示的な型名をテンプレート型の変数名に置き換えます。

例えば、あなたのコードでは、あなたがstruct1は、一般的なようにしたいので、私たちはTに置き換えます(struct1)はsizeofよう

template<class T> 
class LinkedList { 
    public:  
    node *first;  
    int nbrOfNodes;  LinkedList();  
    void addNode(T);  
    T getNode();  
    bool isEmpty(); 

}; 
+0

ありがとうございます、私はポイントを報酬できませんが、私は教育的な例に感謝します – itsaboy

0

struct1とstruct2は、バイト単位で異なるサイズを持っています!= sizeof(struct2)。関数から構造体を返すには、コピーする必要があります。したがって、正しいバイト数をコピーできるように、正しい型を指定する必要があります。正しいこの問題を開始するには、非常に低いレベルで考える必要があります。

struct GenericStruct { 
    void *ptr; 
    size_t size; 
    type_info t; 
}; 
struct1 extract_struct1(GenericStruct &s); 
struct2 extract_struct2(GenericStruct &s) 
    { 
    if (s.size != sizeof(struct2)) throw -1; 
    if (s.t != typeid(struct2)) throw -1; 
    struct2 *s2 = (struct2*)s.ptr; 
    return *s2; 
    } 
GenericStruct make_generic(const struct1 &ss) 
{ 
GenericStruct s; 
s.ptr = (void*)&ss; 
s.size = sizeof(struct1); 
s.t = typeid(struct1); 
return s; 
} 
GenericStruct make_generic(const struct2 &ss); 

本当の問題は、サイズや種類が一致しない場合、これらの機能は、実行時に失敗することができるということです。コピーが明らかにも必要とされている。これらの基本的なプリミティブ後

GenericStruct Copy(const GenericStruct &s); 

を、あなたはコピーコンストラクタと適切な一般的な構造体のサポートを実装するために、これらの機能を使用して代入演算子を持つクラスを作成することができますが存在します。

関連する問題