1

私は C++ プロジェクトに取り組んでいますが、このリンカ エラーを軽減する方法がわかりません。ここでは以下です:

1>test4.obj : エラー LNK2019: 未解決の外部シンボル "private: bool __thiscall OrderedList::binarySearch(char,int &)" (?binarySearch@?$OrderedList@VRecord@@D@@AAE_NDAAH@Z) 関数で参照" public: virtual void __thiscall OrderedList::insert(class Record const &)" (?insert@?$OrderedList@VRecord@@D@@UAEXABVRecord@@@Z)

誰かが Visual Studio 2010 が言っていることを分解して翻訳するのを手伝ってくれたら、それは素晴らしいことです (出力を読むのが本当に上手になりたいです)。この特定のエラーについて読んでいますが、コードに適用される理由をまだ理解していません。

編集: binarySearch メソッドは OrderedList.cpp ファイルに実装されています。メインを含むファイルで #include "OrderedList.cpp" ステートメントも使用しています。

問題の 2 つの関数:

プロトタイプを挿入:

virtual void insert ( const DataType &newDataItem ) throw ( logic_error );

入れる:

template <typename DataType, typename KeyType>
void OrderedList<DataType, KeyType>::insert(const DataType &newDataItem) 
throw (logic_error ) {
int index = 0;
if (size == maxSize) {
    throw logic_error("List is full.");
} 
else { 
    KeyType searchKey = newDataItem.getKey();
    if (binarySearch(searchKey, index)) {
        cursor = index;
        dataItems[cursor] = newDataItem;
    }
    else {
        cursor = index;
        insert(newDataItem);
    }
} 
}

二分探索のプロトタイプ:

bool binarySearch ( KeyType searchKey, int &index );

二分探索:

template < typename DataType, typename KeyType >
bool binarySearch (KeyType searchKey, int &index ) {
int low  = 0;        // Low index of current search range
int high = size - 1;    // High index of current search range
bool result;            // Result returned

while ( low <= high )
{
    index = ( low + high ) / 2;               // Compute midpoint
    if ( searchKey < dataItems[index].getKey() )
       high = index - 1;                      // Search lower half
    else if ( searchKey > dataItems[index].getKey() )
       low = index + 1;                       // Search upper half
    else
       break;                                 // searchKey found
}

if ( low <= high )
   result = true;       // searchKey found
else
{
   index = high;        // searchKey not found, adjust index
   result = false;
}

return result;
}

さらに、 Record クラス:

class Record
{
public: 
Record () { key = char(0); }
void setKey(char newKey) { key = newKey; }
char getKey() const { return key; }

private:
char key;

};

4

3 に答える 3

1

これを1行ずつ分類してみましょう。

1>test4.obj : error LNK2019: unresolved external symbol 

これは、test4.objファイルで、コンパイラーが、使用可能であると期待していたコンパイル済みオブジェクトを見つけることができなかったことを示しています。

"private: bool __thiscall OrderedList::binarySearch(char,int &)" 

これは、オブジェクト(この場合はメンバー関数)の関数シグネチャであり、検出できません。

(?binarySearch@?    $OrderedList@VRecord@@D@@AAE_NDAAH@Z) 

これは、上記の関数の「マングル名」です。これは、コンパイラによってオブジェクトファイルに付けられた名前です。これは、コンパイラーが類似した名前で異なるタイプの関連付けを持つオブジェクトを検証するためのテキストによる方法を提供します。

referenced in function 

これは、次のオブジェクトが未解決のシンボルが参照された場所になることを示す行です。

"public: virtual void __thiscall OrderedList::insert(class Record const &)"

これは、エラーの原因となったシンボルを呼び出したオブジェクトの関数シグネチャです。テンプレートパラメータはここには表示されませんが、型にバインドされた引数は表示されるためDataType、型はわかりRecordますが、何であるかはわかりませんKeyType

(?insert@?$OrderedList@VRecord@@D@@UAEXABVRecord@@@Z)

これは、上記の関数のマングル名です。


それでは、これが何を意味するのかを見てみましょう。グローバル関数テンプレートのように見えるものを呼び出すテンプレートメソッドがあります。そのグローバル関数テンプレートには2つのテンプレートパラメーターがあり、そのうちの1つだけが関数の呼び出しによって提供されます。

つまり、を指定しなかったDataTypeため、コンパイラは関数テンプレートのテンプレート特殊化を生成する方法を知りませんbinarySearch

ここでの朗報は、実際にはDataTypeテンプレートパラメータは必要ないため、単純に削除しても問題ないはずです。その時点で、関数テンプレートは完全に特殊化され、コンパイルされるはずです。

于 2012-10-10T21:02:58.870 に答える
1

テンプレート関数は、適切なテンプレート パラメーターを指定して呼び出すまで、実際には関数ではありません。この場合、OrderedList.cpp ファイルには関数の呼び出しが含まれていなかったため、実際の関数コードは生成されませんでした。そのため、リンカーはそれを見つけることができません。

通常、テンプレート関数またはクラスは、この問題を回避するためにヘッダー ファイルで定義されます。

于 2012-10-10T20:44:43.027 に答える
1

次の行が可能ですか:

template < typename DataType, typename KeyType >
bool binarySearch (KeyType searchKey, int &index )

は cpp ファイルにあり、次のように実装するのを忘れています。

template < typename DataType, typename KeyType >
bool OrderedList<DataType, KeyType>::binarySearch(KeyType searchKey, int &index)

次にbinarySearch、単なるグローバル関数であり、OrderedList検索しようとするリンカの関数でOrderedList<DataType, KeyType>::binarySearchはなく、指定された関数としてカウントしないでください??!

于 2012-10-10T20:58:53.170 に答える