尝试使用多态性C++时发生编译错误

compile error when trying to use polymorphism C++

本文关键字:编译 错误 C++ 多态性      更新时间:2023-10-16

我有一个基类Model,它在Model.h中声明并实现,它还包括保护:

#ifndef Model_h
#define Model_h
#include <iostream>
#include <conio.h>
#include "Node.h"
#include <map>
using namespace std;
class Node;
class Model
{
public:
    void add(Node*);
protected:
    map<int, Node> nodes;
};
void Model::add(Node *n)
{
    nodes.insert(make_pair(n->returnTag(),*n));
}
#endif

我想要一个子类Node,它在Node.h中声明和实现,也包含保护-继承Model类,如下所示:

#ifndef Node_h
#define Node_h
#include <map>
#include <vector>
#include "Model.h"
class Node;
map<int, map<int, Node>> tnodeMap;
map<int, Node>::iterator nodeIter;
class Node:public Model
{
public:
    Node();
    int returnTag();
   /*some code*/
};
/*implementation*/
#endif

但当我尝试构建它时,我得到了错误C2027未定义的类型"节点"如果我省略Model.h中的class Node;语句,我会得到节点标识符的语法错误

我很困惑问题出在哪里?

您的问题与多态性无关,而是与循环依赖有关。不能在Model中声明节点容器(如map<int, Node> nodes),因为这会为Model创建对Node的依赖关系。然而,Node依赖于Model(因为Node继承自Model)。

因此出现了问题。

然而,还有其他几个问题。

  1. 为什么Model中的add方法需要一个Node指针,然后继续到一个副本(通过在地图中插入*n)?谁拥有那个指针?它的寿命是多少
  2. 为什么在Node类中全局定义了另一个Node映射
  3. 为什么NodeModel类在它们各自的头文件中实现?由于ModelNode之间存在复杂的依赖关系,如果将Node对象与标头混合,则无法实现Model取消引用Node对象。当您不使用模板时,应该将声明和实现分开
  4. ModelNode之间有什么关系?你能说Node就是Model吗?这种等级制度在我看来很奇怪

无论如何,这里有一个固定的例子应该有效(尽管未经测试)。

型号.h

#ifndef Model_h
#define Model_h
#include <iostream>
#include <map>
#include <conio.h>
// We SHOULD NOT include Node.h in this file
class Node; // Forward declaration is enough
using namespace std;
class Model
{
public:
    void add(Node*);
protected:
    map<int, Node*> m_nodes;
};
#endif // Model_h

型号.cpp

#include "Model.h"
// In the implementation file we CAN NOW include Node.
#include "Node.h"
void Model::add(Node* n)
{
    m_nodes.insert(make_pair(n->returnTag(), n));
}

节点.h

#ifndef Node_h
#define Node_h
#include <map>
#include <vector>
#include "Model.h"
// NO NEEED to forward declare the Node class
map<int, map<int, Node>> tnodeMap; // Why is this global?
map<int, Node>::iterator nodeIter; // Why is this global?
class Node: public Model
{
public:
    Node();
    int returnTag();
   /*some method declarations*/
};
/* implementation IN IMPLEMENTATION FILE */
#endif // Node_h

您的两个头文件是相互依赖的。使一个头文件独立。

如果编译器试图编译第一个节点.h,它将在该文件中找到include model.h。所以它会跳转到model.h来编译它。在这里,它找到了model.h