编辑:当我将link_def.cpp与link_dec.h合并时,我只会得到第一个错误,而不是第二个错误。
当我尝试编译一些代码时,出现了这些链接器错误:
码:
#include"list_dec.h"
#include"catch.h"
int main()
{
list<int, 100> L1;
try
{
L1.return_current();
}
catch(err)
{
return -1;
}
return 0;
}
错误:
Linking...
main.obj : error LNK2019: unresolved external symbol "public: __thiscall list<int,100>::~list<int,100>(void)" (??1?$list@H$0GE@@@QAE@XZ) referenced in function __catch$_main$0
main.obj : error LNK2019: unresolved external symbol "public: int __thiscall list<int,100>::return_current(void)" (?return_current@?$list@H$0GE@@@QAEHXZ) referenced in function _main
main.obj : error LNK2019: unresolved external symbol "public: __thiscall list<int,100>::list<int,100>(void)" (??0?$list@H$0GE@@@QAE@XZ) referenced in function _main
如果有人需要list_dec.h,catch.h和list_def.cpp(列表类的定义)的代码,则只需评论一下,尽管它们很无关紧要,但我不想包括它们,因为它们很大。
由于有人想查看list_dec.h(我暂时将其与list_def.cpp合并了)
list_dec.h:
template<class T, size_t limit>
class list
{
public:
//constructors
list();
list(const list<T, limit>& lst);
~list();
//assignment operator
void operator=(const list<T, limit>& lst);
//append new items
void append(const T& item);
//clear the list
void clear();
//return current item
T return_current();
//test if item is last item
bool last();
//make current item head of the list
void make_head();
//move to the next item
bool next();
//interrogation
size_t return_count();
size_t return_limit();
protected:
size_t count; //# of items in list
size_t current; //current item
T data[limit]; //array of elements of list
//internal functions
void copy(const list<T, limit>& lst);
};
//copier function
template<class T, size_t limit>
void list<T, limit>::copy(const list<T, limit>& lst)
{
count = lst.count;
current = lst.current;
for(size_t n = 0; n < count; n++)
{
data[n] = lst.data[n];
}
return;
}
//constructor
template<class T, size_t limit>
inline list<T, limit>::list()
{
count = 0;
current = 0;
}
//copy constructor
template<class T, size_t limit>
inline list<T, limit>::list(const list<T, limit>& lst)
{
copy(lst);
}
//assignment operator
template<class T, size_t limit>
inline void list<T, limit>::operator=(const list<T, limit>& lst)
{
clear();
copy(lst);
return;
}
//destructor
template<class T, size_t limit>
inline list<T, limit>::~list()
{
clear();
}
//append function
template<class T, size_t limit>
void list<T, limit>::append(const T& item)
{
if(count == limit)
{
throw CX_OVERFLOW;
}
data[count] = item;
count++;
return;
}
//return current item
template<class T, size_t limit>
T list<T, limit>::return_current()
{
if(count == 0)
{
throw CX_NULL;
}
if(current == count)
{
throw CX_ATEND;
}
return data[current];
}
//test if <current> pointer is at tail
template<class T, size_t limit>
inline bool list<T, limit>::last()
{
if(current == count)
{
return true;
}
else
{
return false;
}
}
//set current pointer to head
template<class T, size_t limit>
inline void list<T, limit>::make_head()
{
current = 0;
return;
}
//set current pointer to next pointer in list
template<class T, size_t limit>
bool list<T, limit>::next()
{
if(count == 0)
{
throw CX_NULL;
}
if(current == count)
{
throw CX_ATEND;
}
current++;
if(current == count)
{
return false;
}
return true;
}
//interrogation functions
template<class T, size_t limit>
inline size_t list<T, limit>::return_count()
{
return count;
}
template<class T, size_t limit>
inline size_t list<T, limit>::return_limit()
{
return limit;
}
最佳答案
可以很轻松地读取链接器错误。试一试吧:
main.obj : error LNK2019: unresolved external symbol "public: __thiscall list<int,100>::~list<int,100>(void)" (??1?$list@H$0GE@@@QAE@XZ) referenced in function __catch$_main$0
main.obj
中,该文件是从main.cpp生成的目标文件。 list<int,100>::~list<int,100>(void)"
告诉我们问题出在类模板列表的析构函数上,该模板专门用于<int, 100>
。这部分的格式很好,非常简单。对于第二个错误,我们还看到了返回类型:int __thiscall list<int,100>::return_current(void)
。也就是说,一个返回int,使用__thiscall调用约定,属于列表的函数称为return_current,并且不带任何参数。 ??1?$list@H$0GE@@@QAE@XZ
几乎可以忽略。这是符号的名称,由编译器修饰,因此这是链接器在.obj文件中寻找的名称。但是由于链接程序已经告诉我们该符号的可读C++名称,因此我们实际上不需要此名称。 (除非您决定自己亲自挖掘.obj文件)。 所以你有它。第一个错误指出找不到列表的析构函数的定义。如果该函数未在类定义中声明为内联,则应在另一个.cpp文件中进行定义。我假设这是您的
list_def.cpp
,并且该文件也将被编译并传递给链接器。但是,这导致我们在模板上遇到了一个小问题。它们是编译时构造,在编译器为其发出代码之前必须实例化模板。在编译器的输出中,类模板
list
或特化list<int, 84>
均不存在任何代码,因为未使用该特化。编译器仅生成实际需要的特化。并且,当编译器处理list_def.cpp时,似乎不需要专门化。它无法查看其他.cpp文件,例如您的main.cpp。它只会看到当前正在编译的.cpp文件,以及所有
#include
的文件。由于看不到list<int, 100>
,因此不会为该特化生成任何代码,因此,当将目标文件传递给链接器时,它无法找到list<int, 100>
符号的定义并发出错误。通常的解决方案是在 header 中内联定义类模板的所有成员。这样,该定义对于包括头文件在内的任何编译单元都是可见的,因此编译器可以创建所需的模板特化名称。
具体来说,以下将产生链接器错误:
// .h
template <int n>
class Foo {
int Bar();
};
// .cpp
template <int n>
int Foo::Bar() {
return n; // Error: This is not visible from other .cpp files
}
因此,只需将.cpp内容移动到标题中:
// .h
template <int n>
class Foo {
int Bar();
};
template <int n>
int Foo::Bar() {
return n; // Error: This is will cause the function to be defined in every .cpp file that includes it, so you'll get a *different* linker error instead (multiple definitions)
}
但这有效,并且是通常的解决方案
// .h
template <int n>
class Foo {
int Bar() { return n; } // just define it here, inside the class definition, and it is implicitly inline, so it's ok that multiple .cpp files see it
};
或者:
// .h
template <int n>
class Foo {
int Bar();
};
// still in .h
template <int n>
inline int Foo::Bar() { // explicitly marking it inline works too. Now the compiler knows that it might be defined in multiple .cpp files, and these definitions should be merged back together
return n;
}
一个更不寻常但偶尔有用的解决方案是在定义它的编译单元中显式实例化该模板。因此,在
list_def.cpp
中,在模板定义之后添加以下行:template class list<int, 100>;
这告诉编译器专门为该特化生成代码,即使本编译单元中未使用它也是如此。显然,这种方法仅在您事先知道需要哪些专业的情况下才有用。
编辑:
似乎您从未定义过从析构函数调用的
clear()
函数。这就是在 header 中包含所有内容之后最终链接器错误的原因。
关于c++ - 这些链接错误是什么意思? (C++)(MSVC++),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/860093/