Reputation: 965
I am writing a simple Queue class (for exercise). This Project consists of a simple integer Node Class, which Queue Class utilizes, and the Queue class it self.
During build I am getting 3 different linker errors in my c++ project, listed below:
Error LNK2005 "public: __thiscall Node::Node(int)" (??0Node@@QAE@H@Z) already defined in fmQueue.obj Queue
Error LNK2005 "public: __thiscall Node::Node(void)" (??0Node@@QAE@XZ) already defined in fmQueue.obj Queue
Error LNK1169 one or more multiply defined symbols found Queue
I did look at where i am introducing my classes, however i dont understand where this isuue is coming from.
My code:
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;
}
Upvotes: 0
Views: 2940
Reputation: 1321
Instead of putting #include "node.h" inside the other headers, put it inside the .cpp.
Then you must forward declare the type in fmQueue.h.
// fmQueue.h
class Node;
namespace fm
{
class fmQueue
{
Node *_head, *_tail;
void clearbuf();
.....
// fmQueue.cpp
#include "fmQueue.h"
#include "Node.h"
....
The compiler just needs to know that there will be a type 'class Node' at this time, it doesn't need to know any of the members or methods of Node.
Upvotes: 0
Reputation: 49251
It's a common problem that's caused by having an implementation in a header file.
What happens is that your fmQueue.cpp compilation unit compiles, and defines the constructor functions.
After that, the main.cp compiles and defines the same functions (because they are visible in the included header file).
So when the linker tries to link the 2 compilation units together it detects the double definition.
So, that's why you should implement functions in the .cpp file.
Another solution would be to decouple the header dependency. You can forward declare the Node class in the queue's header, and only actually include the header in the queue's cpp file.
Upvotes: 1