我正在 Visual Studio 中练习 LinkedList 实现,代码在 Visual Studio 中运行良好。但由于我大部分时间都使用 vscode,所以我遵循了 来自 vscode 官方网站的教程。给定链接中的演示代码构建并成功运行,没有任何错误或警告。但是当我尝试构建 LinkedList c++ 项目时,每个函数都会出现错误,并且构建退出。错误如下
LinkedList.obj : error LNK2019: unresolved external symbol "public: __thiscall
List::List(void)" (??0List@@QAE@XZ) referenced in function _main
LinkedList.obj : error LNK2019: unresolved external symbol "public: void __thiscall List::addNode(int)" (?addNode@List@@QAEXH@Z) referenced in function _main
LinkedList.obj : error LNK2019: unresolved external symbol "public: void __thiscall List::deleteNode(int)" (?deleteNode@List@@QAEXH@Z) referenced in function _main
LinkedList.obj : error LNK2019: unresolved external symbol "public: void __thiscall List::printList(void)" (?printList@List@@QAEXXZ) referenced in function _main
我实际上不知道我在哪里犯了错误,因为这是我第一次尝试在 VScode 上运行 C++ 代码。下面给出了我的 CPP、头文件和驱动程序文件。
列表.h
#ifndef LIST_H
#define LIST_H
class List {
private:
typedef struct node {
int data;
node* next;
}*nodePtr;
nodePtr head;
nodePtr current;
nodePtr temp;
public:
List();
void addNode(int addData);
void deleteNode(int delData);
void printList();
};
#endif
列表.cpp
#include <iostream>
#include <cstdlib>
#include "List.h"
using namespace std;
List::List() {
head = NULL;
current = NULL;
temp = NULL;
}
void List::addNode(int addData) {
nodePtr n = new node;
n->next = NULL;
n->data = addData;
if (head != NULL) {
current = head;
while (current->next != NULL) {
current = current->next;
}
current->next = n;
}
else head = n;
}
void List::deleteNode(int delData) {
nodePtr delPtr = NULL;
temp = head;
current = head;
while (current != NULL && current->data != delData) {
temp = current;
current = current->next;
}
if (current == NULL) {
cout << delData << " not found.\n";
delete delPtr;
}
/**/
else {
delPtr = current;
current = current->next;
temp->next = current;
if (delPtr == head) {
head = head->next;
}
delete delPtr;
cout << delData << " was deleted.\n";
}
}
void List::printList() {
if (head == NULL) {
cout << "list is empty";
}
else {
current = head;
while (current != NULL) {
cout << current->data << endl;
current = current->next;
}
}
}
LinkedList.cpp
#include <cstdlib>
#include "List.h"
#include <iostream>
int main() {
List demo;
demo.addNode(6);
demo.addNode(12);
demo.addNode(45);
demo.addNode(67);
demo.printList();
demo.deleteNode(6);
demo.deleteNode(12);
demo.printList();
}
如果有人能指出我在哪里犯了错误,那就太好了。我真的不想打开像 Visual Studio 这样的重型应用程序来练习我的代码。短暂性脑缺血发作。
由于当前的“答案”都不适用(一个是错误的,另一个是非常糟糕的做法,导致以后出现类似的错误),这里有一个解决方案。
免责声明:我通常使用 CMake 为我创建构建,这意味着我不熟悉如何在 VSCode 中执行此操作,因此这是一种不是最佳的方法。 (原因是在这个解决方案中,所有文件都是同时编译的,这意味着每当您更改任何文件时,都必须重新编译所有文件,而不是重新编译更改的文件并再次链接。)
如果您的目录中有所有文件,例如:
project_root/
- List.h
- List.cpp
- LinkedList.cpp
然后你可以使用:
{
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"label": "cl.exe build active file",
"command": "cl.exe",
"args": [
"/Zi",
"/EHsc",
"/Fe:",
"${fileDirname}\\${fileBasenameNoExtension}.exe",
"project_root/*.cpp"
],
"problemMatcher": ["$msCompile"],
"group": {
"kind": "build",
"isDefault": true
}
}
]
}
理论上这应该可行。
错误的示例:
假设你有:
---------------- B.h ---------------------
// Omitted ifndef guard
void addOne(int&);
---------------- B.cpp ---------------------
void addOne(int& addTo){
++addTo;
}
---------------- A.cpp ---------------------
#include "B.h"
int main(){
int a = 0;
addOne(a);
return a;
}
现在编译器的任务是将
A.cpp
转换为“机器代码”。首先,它执行预处理器指令(在本例中将 B.h
的内容粘贴到 A.cpp
的顶部)将 A.cpp
转换为:
void addOne(int&);
void main(){
int a = 0;
addOne(a);
return a;
}
之后它会编译它。编译器不知道
addOne
的作用。它只知道它的样子(接受一个 int&
参数并返回 void
)。编译器完成生成“机器代码”后,链接器接管控制权,其任务是:将所有内容放在一起,使其有意义。 “机器代码”没有运行所需的所有内容,因此链接器解析引用(即,它看到您向其传递了两个目标文件(由编译器生成)。其中一个引用 void addOne(int&)
,但从未实现它,而另一个只是实现它。)。然后它将它们打包成一个可执行文件,您可以运行它。
存在未解析的引用的原因是因为
List.cpp
未编译,并且未传递给链接器,因此无法找到如何运行List.cpp
中声明的函数。
请注意,如果您想使用
#include "List.cpp"
“解决方案”,您可以,但是在 List.cpp
中声明所有内容以具有 static
链接将是有益的,否则稍后您可能会遇到相反的错误(即多个定义同样的事情)。
https://zhuanlan.zhihu.com/p/352148624
在
#include
之后链接丢失的库(注意#pragma
仅在msvc中,gcc会出错)
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "xxx.lib")
...
<winuser.h>
user32.lib