简体   繁体   中英

Understanding this error (LNK 2019) in Visual Studio 2010

Alright so I'm working on a C++ project and I just can't figure out how to alleviate this linker error. Here it is below:

1>test4.obj : error LNK2019: unresolved external symbol "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 &)" (?insert@?$OrderedList@VRecord@@D@@UAEXABVRecord@@@Z)

If someone could help breakdown and translate to me what Visual Studio 2010 is saying that would be amazing (I really want to get better at reading the Output). I have been reading up on this particular error, but I'm still not understanding why it is applying to my code.

EDIT: The binarySearch method is being implemented in the OrderedList.cpp file. I'm also using an #include "OrderedList.cpp" statement in the file which contains my main.

The two functions in question:

Insert prototype:

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

Insert:

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);
    }
} 
}

Binary Search prototype:

bool binarySearch ( KeyType searchKey, int &index );

Binary Search:

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;
}

Additionally, the Record class:

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

private:
char key;

};

A template function isn't really a function until you call it with the proper template parameters. In this case since the OrderedList.cpp file didn't contain a call of the functions, the actual function code was never generated. That's why the linker can't find it.

Usually template functions or classes are defined in header files to avoid this problem.

Is it possible that the line:

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

is in your cpp file and you just forget to implement it as:

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

Then binarySearch is just a global function and not a function from OrderedList and linker that try to find OrderedList<DataType, KeyType>::binarySearch don't count it as specified function??!

Let's break this down line-by-line:

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

This is telling you that in the test4.obj file, the compiler was unable to find a compiled object that it was expecting to have available.

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

This is the function signature of the object (a member function, in this case) that it can't find.

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

This is the "mangled name" of the above function -- the name that it is given by the compiler in the object file. It provides a textual way for the compiler to validate objects with similar names but different type associations.

referenced in function 

This is a line that tells you that the next object is going to be the place where the unresolved symbol was referenced.

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

This is the function signature of the object that invoked the symbol that led to the error. Note that the template parameters are not visible here, but any type-bound arguments are, so you know DataType is of type Record , but you don't know what KeyType is.

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

This is the mangled name for the function above.


Now, let's look at what this means. You have a template method that is invoking what appears to be a global function template. That global function template has two template parameters, only one of which is supplied by the invocation of the function.

In other words, you didn't provide DataType , so the compiler doesn't know how to generate the template specialization of the function template binarySearch .

The good news here is that you don't actually need the DataType template parameter, so you should be fine to simply eliminate it. At that point, your function template will be fully specialized and should compile.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM