1

双方向リンク リストを実装するプログラムを作成しています。私の問題は、コマンドを発行して if をコンパイルするときです

g++ -g -Wall DynamicSequenceVector.cpp DynamicSequenceVector.h main.cpp 

次のコンソール出力が表示されます

/tmp/cc6P5VZK.o: In function `main':
main.cpp:(.text+0x1a): undefined reference to `DynamicNode::DynamicSequenceVector<int>::DynamicSequenceVector(int)'
main.cpp:(.text+0x3a): undefined reference to `DynamicNode::DynamicSequenceVector<int>::~DynamicSequenceVector()'
main.cpp:(.text+0x4f): undefined reference to `DynamicNode::DynamicSequenceVector<int>::~DynamicSequenceVector()'
collect2: error: ld returned 1 exit status

これは、main.cpp にファイルをインポートする方法に問題があると感じています。main 関数を DyanmicSequenceVector.cpp ファイルに移動すると、完全に正常にコンパイルされるからです。さらに、これらのコンパイル エラーは、パラメーターを使用して新しいオブジェクトを構築するときにのみ発生します。

DynamicSequenceVector.h

#ifndef __DYNAMIC_VECTOR
#define __DYNAMIC_VECTOR

namespace DynamicNode {

template <class Type>
class DynamicSequenceVector {
    private:
        struct dynamicNode {
            dynamicNode *previousLink;
            dynamicNode *nextLink;
            Type data;
            int position;
        };

        int nodeCount;
        int currentPosition;
        dynamicNode *headNode;
        dynamicNode *tailNode;
        dynamicNode *currentNode;
        dynamicNode *tempNode;

    public:
        DynamicSequenceVector();
        DynamicSequenceVector(Type data);
        ~DynamicSequenceVector();
        void appendNode(Type nodeData);
        void accessData(int startingPosition, int endingPosition);
};

}
#endif

DynamicSequenceVector.cpp

#include <iostream>
#include "DynamicSequenceVector.h"

using namespace std;
using namespace DynamicNode;

template <typename Type>
DynamicSequenceVector<Type>::DynamicSequenceVector() {
    nodeCount       = 0;
    currentPosition = NULL;
    headNode        = NULL;
    tailNode        = NULL;
    currentNode     = NULL;
}

template <typename Type>
DynamicSequenceVector<Type>::DynamicSequenceVector(Type nodeData) {
    nodeCount              = 1;
    currentPosition        = 0;
    headNode               = new dynamicNode;
    headNode->previousLink = NULL;
    headNode->nextLink     = NULL;
    headNode->data         = nodeData;
    headNode->position     = 0;
    currentNode            = 
}

template <typename Type>
DynamicSequenceVector<Type>::~DynamicSequenceVector() {
    while(nodeCount != 0) {
        tempNode = tailNode->previousLink;
        delete tailNode;
        tailNode = tempNode;
    }
    return;
}

template <typename Type>
void DynamicSequenceVector<Type>::appendNode(Type nodeData) {
    if (currentPosition == 0) {
        headNode               = new dynamicNode;
        headNode->data         = nodeData;
        headNode->position     = 0;
        headNode->previousLink = NULL;
        headNode->nextLink     = NULL;
    } else {
        tempNode               = new dynamicNode;
        tempNode->data         = nodeData;
        tempNode->previousLink = tailNode;
        tempNode->position     = nodeCount + 1;
        tailNode->nextLink     = tempNode;
        tailNode               = tempNode;
    }

    nodeCount++;
}

template <typename Type>
void DynamicSequenceVector<Type>::accessData(int startingPosition, 
        int endingPosition) {
    cout << "Data accessed";
    return 0;
}

main.cpp

#include <iostream>
#include "DynamicSequenceVector.h"

//using namespace std;
using namespace DynamicNode;

int main() {
    DynamicSequenceVector<int> test();
    DynamicSequenceVector<int> testingVector(5); // gives an error
    //test = new DynamicSequenceVector<char>::DynamicSequenceVector();

    std::cout << "Hello world!\n";
}
4

2 に答える 2

3

テンプレートメンバーの実装は、個別の.cppファイルではなく、ヘッダーに含める必要があります。

main.cppをコンパイルする場合、コンパイラーはインスタンス化するために実装が表示される必要がDynamicSequenceVector<int>あり、それらは使用できません。したがって、コンパイラは、テンプレートのインスタンス化が別のコンパイルユニットで利用可能であると想定しますが、そうではないため、リンカは失敗します。

(DynamicSequenceVector.cppファイルは、ここでは何の役にも立ちません。インスタンス化されていないテンプレートメンバーは、意味がないため、実際にはオブジェクトファイルに書き出されません。コンテンツをヘッダーファイルに移動してから、を削除します。 cppファイルは、この問題を解決する正しい方法です。)


または、これをDynamicSequenceVector.cppの下部に追加することもできます。

template class DynamicSequenceVector<int>;

これにより、このバージョンのテンプレートクラスをインスタンス化し、そのコンパイルユニットで使用可能にしてエクスポートするようにコンパイラに指示します。次に、リンカがmainのコンパイルユニットでシンボルを解決しようとすると、それらを見つけることができます。

ただし、これは、このテンプレートクラスのすべてのインスタンス化の集中リストを維持する必要があることを意味します。これは大変な作業であり、通常は悪い考えと見なされます。

于 2013-03-21T18:45:12.397 に答える
1

メインはhファイルしか知らないため、cppでテンプレート化されたコードの実装を使用することはできません。テンプレート化された実装をhファイルに移動する必要があります。

于 2013-03-21T18:45:39.623 に答える