2017-04-18 146 views
0

我正在写一个简单的Queue类(用于练习)。这个项目由Queue Class使用的一个简单的整数节点类和它自己的Queue类组成。visual studio链接器错误

在生成过程中我得到我的C++项目,3个不同的链接错误列举如下:

  1. 错误LNK2005 “市民:__thiscall节点::节点(INT)”(?? 0Node @@ QAE @ H + Z) 在fmQueue.obj队列已经定义

  2. 错误LNK2005 “公共:__thiscall节点::节点(无效)”(?? 0Node @@ @ QAE XZ) 已经在fmQueue.obj队列

    定义
  3. 错误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; 
} 

回答

1

这是一个常见的问题,是由头文件中的实现引起的。
会发生什么是您的fmQueue.cpp编译单元编译并定义构造函数。 之后,main.cp编译并定义相同的函数(因为它们在包含的头文件中是可见的)。
所以,当链接器试图将2个编译单元链接在一起时,它会检测到双重定义。

所以,这就是为什么你应该在.cpp文件中实现函数的原因。
另一个解决方案是解耦头依赖。您可以在队列头中转发声明Node类,并且只在队列的cpp文件中包含该头。

+0

完美的解释,将Node类的实现移到一个cpp文件解决了问题。谢谢 – BlooB

0

代替将#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" 
.... 

编译器只需要知道,会有一种“类节点”在这个时候,它并不需要知道任何节点的成员或方法。