什么是未定义的参考/未解析的外部符号错误?常见原因是什么?如何解决/预防?


当前回答

我在头文件中声明函数的原型时遇到了这个问题:

int createBackground(VertexArray rVA,IntRect arena);

但随后使用具有第一个参数的引用在其他地方定义函数:

int createBackground(VertexArray&rVA,IntRect arena){}

原型没有在第一个参数中使用引用,而定义是,这一事实导致了这个问题。当我将两者都更改为正确匹配包含引用或不包含引用时,问题得到了解决。

干杯

其他回答

跨模块.dll(编译器特定)错误地导入/导出方法/类。

MSVS要求您使用__declspec(dllexport)和__declsspec(dllimport)指定要导出和导入的符号。

这种双重功能通常通过使用宏来实现:

#ifdef THIS_MODULE
#define DLLIMPEXP __declspec(dllexport)
#else
#define DLLIMPEXP __declspec(dllimport)
#endif

宏THIS_MODULE只能在导出函数的模块中定义。这样,声明:

DLLIMPEXP void foo();

扩展到

__declspec(dllexport) void foo();

并且告诉编译器导出函数,因为当前模块包含其定义。当将声明包含在不同的模块中时,它将扩展到

__declspec(dllimport) void foo();

并且告诉编译器,该定义位于链接到的一个库中(另请参见1)。

您可以使用类似的导入/导出类:

class DLLIMPEXP X
{
};

已声明但未定义变量或函数。

典型的变量声明是

extern int x;

由于这只是一个声明,因此需要一个单独的定义。相应的定义如下:

int x;

例如,以下内容将生成错误:

extern int x;
int main()
{
    x = 0;
}
//int x; // uncomment this line for successful definition

类似的注释适用于函数。声明函数而不定义它会导致错误:

void foo(); // declaration only
int main()
{
   foo();
}
//void foo() {} //uncomment this line for successful definition

请注意,您实现的函数与您声明的函数完全匹配。例如,您可能有不匹配的简历限定符:

void foo(int& x);
int main()
{
   int x;
   foo(x);
}
void foo(const int& x) {} //different function, doesn't provide a definition
                          //for void foo(int& x)
                          

不匹配的其他示例包括

函数/变量在一个命名空间中声明,在另一个命名空间定义。函数/变量声明为类成员,定义为全局(反之亦然)。函数返回类型、参数编号和类型以及调用约定并不完全一致。

来自编译器的错误消息通常会给出已声明但从未定义的变量或函数的完整声明。将其与您提供的定义进行比较。确保每个细节都匹配。

在我的例子中,语法是正确的,但当一个类调用同一DLL中的第二个类时,我出现了错误。第二个类的CPP文件在visual studio中具有错误的财产->项类型,在我的例子中,它被设置为C/C++头,而不是正确的C/C++编译器,因此编译器在构建CPP文件时没有编译它,并导致错误LNK2019

下面是一个示例,假设语法正确,您应该通过更改财产中的项类型来获得错误

//class A header file 
class ClassB; // FORWARD DECLERATION
class ClassA
{
public:
ClassB* bObj;
ClassA(HINSTANCE hDLL) ;
//  member functions
}
--------------------------------
//class A cpp file   
ClassA::ClassA(HINSTANCE hDLL) 
{
    bObj = new ClassB();// LNK2019 occures here 
    bObj ->somefunction();// LNK2019 occures here
}
/*************************/

//classB Header file
struct mystruct{}
class ClassB{
public:
ClassB();
mystruct somefunction();
}

------------------------------
//classB cpp file  
/* This is the file with the wrong property item type in visual studio --C/C++ Header-*/
ClassB::somefunction(){}
ClassB::ClassB(){}

Microsoft提供了一个#pragma,以在链接时引用正确的库;

#pragma comment(lib, "libname.lib")

除了库路径(包括库的目录)之外,这应该是库的全名。

需要考虑的一些拼写错误:(我作为初学者经常遇到)

如果您使用的是类:请检查您是否没有在定义函数的cpp文件中的函数名之前忘记“classname::”。如果使用forward声明:请确保声明正确的类型。例如:如果要转发声明“结构”,请使用“结构”而不是“类”。