严重性 代码 说明 项目 文件 行 禁止显示状态 错误 LNK2019 无法解析的外部符号 "public: void __thiscall XXX

本文解析了在VS2017中使用C++模板函数时遇到的错误及其解决方法,强调了模板函数在头文件中实现的重要性。同时介绍了VSCode环境下模板函数的不同处理方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

VS2017

有一段时间没写c++了,这次用vs2017写c++报这个错又有种熟悉的味道。

原因:c++在写模版函数时(template<class T>之类的),头文件不能与cpp文件分离。这就意味者,你头文件定义的含模版的地方必须在头文件中实现,没用模版定义的地方可以放在cpp中实现

比如这样:

class Caculator
{
private:
	int* data = NULL;
	int dataSIze = 0;
	int dataIndex = 0;
	char* operators = NULL;
	int operatorSize = 0;
	int operIndex = 0;
	long t_result = 0;
public:
	Caculator();
	Caculator(const Caculator& caculator);
	~Caculator();
	template<int N, int M>
	void init(int(&datas)[N], char(&_operators)[M]) {
		data = datas;
		dataSIze = N;
		operators = _operators;
		operatorSize = M;
	}
	long result();
	template<int N, int M>
	long result(int(&datas)[N], char(&_operators)[M]) {
		init(datas, _operators);
		return result();
	}
	long caculate(int a, char _operator, int b);
};

#endif

 

VSCode

不过值得一提的是,在VsCode里有模版的地方也可以不分离,即你这么写,并全部在cpp中实现也是没问题的

但相应地(就我个人情况),在main.cpp 中include的时候,就要写成#include"caculator.cpp" 而不是 #include"caculator.h",

我也不知道为什么,可能是因为vscode没有进行相应的配置,你include头文件他似乎找不到对应的cpp文件,从而导致报错

no refererence 空引用错误

 

<think>我们正在处理一个链接错误LNK2019,意味着在链接阶段找不到某个函数的定义。错误信息:"public:__cdecl该符号在函数main中被引用"这通常发生在以下情况:1.声明了一个函数(特别是类的成员函数)但没有定义(即没有实现)。2.定义存在但没有被正确链接(例如,定义在另一个文件中,但该文件没有参与链接)。3.函数签名(函数名、参数列表、常属性等)在声明和定义处不一致。以下是一个示例,展示如何修复LNK2019错误:```cpp//示例错误代码:main.cppclassMyClass{public:MyClass();//声明了构造函数,但没有在同一个编译单元中定义voiddoSomething();};intmain(){MyClassobj;//这里需要MyClass::MyClass(),链接器找不到定义->LNK2019obj.doSomething();//如果doSomething也没有定义,同样会报错return0;}```修复方法:提供缺失的定义。下面是修复后的代码:```cpp//修复后的代码:main.cppclassMyClass{public:MyClass();//声明voiddoSomething();};//提供构造函数的定义MyClass::MyClass(){//实现构造函数的代码}//提供成员函数的定义voidMyClass::doSomething(){//实现doSomething的代码}intmain(){MyClassobj;//现在可以找到构造函数的定义obj.doSomething();//可以找到成员函数的定义return0;}```如果定义在另一个文件中(例如MyClass.cpp),确保在项目中该文件被编译并链接。另一种常见情况是模板类/函数没有在头文件中实现(因为模板要求实现在头文件中)。例如:```cpp//错误示例:MyTemplate.htemplate<typenameT>classMyTemplate{public:MyTemplate();voiddoSomething();};//没有在头文件中提供定义//正确做法应该是在头文件中定义template<typenameT>MyTemplate<T>::MyTemplate(){//实现}template<typenameT>voidMyTemplate<T>::doSomething(){//实现}```此外,如果使用第三方库,需要确保链接了正确的库文件。下面我们提供一个包含多个文件的示例,展示如何正确组织代码以避免LNK2019。###多文件项目示例####文件:MyClass.h```cpp#pragmaonceclassMyClass{public:MyClass();voiddoSomething();};```####文件:MyClass.cpp```cpp#include"MyClass.h"#include<iostream>MyClass::MyClass(){std::cout<< "Constructorcalled"<< std::endl;}voidMyClass::doSomething(){std::cout<< "Doingsomething"<< std::endl;}```####文件:main.cpp```cpp#include"MyClass.h"intmain(){MyClassobj;obj.doSomething();return0;}```编译链接步骤:1.编译MyClass.cpp->MyClass.obj2.编译main.cpp->main.obj3.链接MyClass.obj和main.obj->得到可执文件如果忘记编译MyClass.cpp,则链接时会报LNK2019。###其他常见原因及解决方法:1.**内联函数定义在源文件中**:如果头文件中声明了一个函数为inline,但定义在源文件中,则其他包含该头文件的源文件无法看到定义。解决方法:将内联函数的定义放在头文件中。2.**函数签名不一致**:声明和定义处函数名或者参数列表有微小差异(例如const修饰符)。检查声明和定义是否完全一致。3.**未链接包含实现的库**:在项目设置中添加依赖库。###高级技巧:使用预编译头文件(避免多次包含导致编译缓慢)但注意,预编译头文件不会影响链接错误。###总结:LNK2019错误的原因主要在于链接阶段找不到函数定义。请检查:-所有声明的函数是否有定义?-定义是否在同一个项目中被编译?-函数签名是否一致?-如果是模板,定义是否在头文件中?§§相关问题§§:1.C++中声明和定义的区别是什么?2.如何正确组织C++多文件项目?3.模板类为什么要求实现在头文件中?4.如何解决使用第三方库时出现的链接错误?</think> ###解决 "LNK2019:无法解析外部符号"错误这个错误发生在C++链接阶段,表示编译器找到了函数声明但找不到对应的实现。以下是完整的解决方案: ```cpp // ================== 示例修复代码 ================== // 正确声明和定义头文件: MathLib.h #pragma once class MathLib { public: // 声明 static int add(int a, int b); static double multiply(double a, double b); // 直接在头文件中定义inline函数 inline int square(int x) { return x * x; } }; // ================== 实现文件: MathLib.cpp ================== #include "MathLib.h" // 在cpp文件中提供实现 int MathLib::add(int a, int b) { return a + b; } double MathLib::multiply(double a, double b) { return a * b; } // ================== 主文件: main.cpp ================== #include <iostream> #include "MathLib.h" // 声明需要在其他地方实现的自定义函数 void printResult(int value); // 需要在另一个文件中实现 // 已实现的函数 void displayMessage() { std::cout << "操作完成" << std::endl; } int main() { // 使用类成员函数 std::cout << "5 + 3 = " << MathLib::add(5, 3) << std::endl; std::cout << "4的平方 = " << MathLib::square(4) << std::endl; // 使用普通函数 printResult(42); displayMessage(); return 0; } // ================== 另一个文件: PrintFunctions.cpp ================== #include <iostream> #include "MathLib.h" // 提供printResult的实现 void printResult(int value) { std::cout << "结果是: " << value << std::endl; } // ================== 项目构建说明 ================== /* 编译命令: g++ -c MathLib.cpp -o MathLib.o g++ -c PrintFunctions.cpp -o PrintFunctions.o g++ -c main.cpp -o main.o g++ main.o MathLib.o PrintFunctions.o -o program */ ``` ### 错误原因及解决方案详解 #### 🧠 常见问题场景及修复方法 1. **声明了函数/类方法但没有实现** ```cpp // 错误示例:头文件中声明但没有相应实现 // MyClass.h class MyClass { public: void missingImplementation(); // LNK2019 }; ``` **修复**: 在源文件中提供实现 ```cpp // MyClass.cpp void MyClass::missingImplementation() { // 实现代码 } ``` 2. **函数签名不匹配** ```cpp // 声明 void processData(int data, bool verbose); // 实现(参数类型不同) void processData(int data) { ... } // LNK2019 ``` **修复**: 确保声明和定义完全匹配 ```cpp void processData(int data, bool verbose) { ... } ``` 3. **库文件未正确链接** ```cpp #include <sqlite3.h> int main() { sqlite3* db; sqlite3_open(":memory:", &db); // LNK2019如果没有链接库 } ``` **修复**:项目中添加库依赖 ``` g++ program.cpp -lsqlite3 ``` 4. **模板实现未在头文件中** ```cpp // MyTemplate.h template<typename T> class MyTemplate { public: void method(); // LNK2019如果实现在cpp中 }; ``` **修复**:头文件中实现模板方法 ```cpp template<typename T> void MyTemplate<T>::method() { ... } ``` ### 🛠 高级解决方案 #### 1. 使用内联函数(适用于小函数) ```cpp // 在头文件中定义 inline void quickOperation() { // 简单实现 } ``` #### 2. 使用匿名命名空间(避免符号冲突) ```cpp // 在cpp文件中 namespace { void internalHelper() { // 只在本编译单元可见 } } ``` #### 3. 创建库项目(适用于大型项目) ```cmake # CMakeLists.txt示例 add_library(MathLib STATIC MathLib.cpp) add_executable(MyApp main.cpp) target_link_libraries(MyApp MathLib) ``` ### 🔍 LNK2019调试技巧 1. 使用`nm`或`objdump`查看目标文件导出的符号 ``` nm -C MathLib.o ``` 2. 在Visual Studio中: - 打开"项目属性 > 链接器 > 输入 > 附加依赖项" - 确保所有库文件路径正确 3. 对于未定义的STL函数,确保在预编译头中包含所有必要头文件 ### 📚 正确的项目结构避免LNK2019 ``` project/ ├── include/ // 头文件 │ ├── MathLib.h │ └── Utils.h ├── src/ // 实现文件 │ ├── MathLib.cpp │ ├── Utils.cpp │ └── main.cpp ├── lib/ // 外部库 │ └── sqlite3.lib └── CMakeLists.txt ``` ### ⚠ 为什么C++需要单独编译和链接? C++分离编译模型: 1. 编译阶段:每个.cpp文件独立编译成目标文件 2. 链接阶段:所有目标文件合并,解决符号引用 3. LNK2019发生在链接器找不到符号定义时
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值