visual studio链接器错误
问题描述:
我正在写一个简单的Queue类(用于练习)。这个项目由Queue Class使用的一个简单的整数节点类和它自己的Queue类组成。visual studio链接器错误
在生成过程中我得到我的C++项目,3个不同的链接错误列举如下:
错误LNK2005 “市民:__thiscall节点::节点(INT)”(?? 0Node @@ QAE @ H + Z) 在fmQueue.obj队列已经定义
-
错误LNK2005 “公共:__thiscall节点::节点(无效)”(?? 0Node @@ @ QAE XZ) 已经在fmQueue.obj队列
定义 错误LNK1169 one or更多重定义符号找到队列
我没有看我在哪里我的介绍课,但我不明白的地方这isuue的来源。
我的代码:
Node.h:
// Node.h
// 1-way linked node for use in simple integer Queue
#ifndef NODE_H
#define NODE_H
class Node
{
public:
Node();
Node(int);
int data;
Node *next;
};
Node::Node()
{
data = -1;
next = nullptr;
}
Node::Node(int x)
{
data = x;
next = nullptr;
}
#endif
fmQueue.h:
#ifndef _FMQUEUE_H
#define _FMQUEUE_H
#include <iostream>
#include "Node.h"
namespace fm
{
class fmQueue
{
Node *_head, *_tail;
void clearbuf();
public:
fmQueue();
~fmQueue();
void deQueue(); // uses front to access data, or remove data
void enQueue(int); // uses back to sort data, or add data
void dumQueue();
//int peek(); // get a copy of the front data without removing it
bool isEmpty();
};
}
#endif /* _FMQUEUE_H */
fmQueue.cpp:
#include "fmQueue.h"
using namespace fm;
//---------Private Methods--------
void fmQueue::clearbuf()
{
_head = _tail = nullptr;
}
//--------Public Methods----------
fmQueue::fmQueue()
{
clearbuf();
}
fmQueue::~fmQueue()
{
clearbuf();
}
bool fmQueue::isEmpty()
{
if (_head == _tail && _head == nullptr)
return false;
else
return true;
}
void fmQueue::enQueue(int data1)
{
Node *tempNode = new Node;
tempNode->next = nullptr;
tempNode->data = data1;
if (_head == nullptr)
{
_head = tempNode;
_tail = tempNode;
}
else
{
_tail->next = tempNode;
}
_tail = tempNode;
}
void fmQueue::deQueue()
{
Node *tempNode = new Node;
if (_head == nullptr)
std::printf("NOOOOP, THE QUEUE IS EMPTY");
else
{
tempNode = _head;
_head = _head->next;
std::cout << "the data dequeued is: " << tempNode->data; //add a print statment to see which node was deleted
delete tempNode;
}
}
void fmQueue::dumQueue()
{
Node *tempNode = new Node;
if (tempNode)
while (tempNode->next != nullptr)
{
std::cout << "Queue :" << tempNode->data;
tempNode = tempNode->next;
}
else
std::cout << "Nothing to show";
}
main.cpp中:
#include"fmQueue.h"
int main()
{
fm::fmQueue my_queue;
my_queue.enQueue(2);
std::cout << "fiirst done" << std::endl;
my_queue.enQueue(4);
std::cout << "second done" <<std::endl;
my_queue.dumQueue();
std::cout << "show done" << std::endl;
my_queue.deQueue();
std::cout << "delete done" << std::endl;
my_queue.dumQueue();
std::cout << "show done" << std::endl;
my_queue.deQueue();
std::cout << "delete done" << std::endl;
return 0;
}
答
这是一个常见的问题,是由头文件中的实现引起的。
会发生什么是您的fmQueue.cpp编译单元编译并定义构造函数。 之后,main.cp编译并定义相同的函数(因为它们在包含的头文件中是可见的)。
所以,当链接器试图将2个编译单元链接在一起时,它会检测到双重定义。
所以,这就是为什么你应该在.cpp文件中实现函数的原因。
另一个解决方案是解耦头依赖。您可以在队列头中转发声明Node类,并且只在队列的cpp文件中包含该头。
答
代替将#include“node.h”放入其他头文件中,将其放入.cpp文件中。
然后你必须在fmQueue.h中声明类型。
// fmQueue.h
class Node;
namespace fm
{
class fmQueue
{
Node *_head, *_tail;
void clearbuf();
.....
// fmQueue.cpp
#include "fmQueue.h"
#include "Node.h"
....
编译器只需要知道,会有一种“类节点”在这个时候,它并不需要知道任何节点的成员或方法。
完美的解释,将Node类的实现移到一个cpp文件解决了问题。谢谢 – BlooB