【问题标题】:Compiler Error: error: ‘ListNode’ does not name a type编译器错误:错误:“ListNode”未命名类型
【发布时间】:2015-09-02 23:13:28
【问题描述】:

我正在尝试编写我的类和结构实现文件。该类具有结构中的变量。我不断收到错误:

LinkedList.h:70:8:错误:“ListNode”未命名类型 ListNode* 头部;

LinkedList.h:71:8:错误:“ListNode”未命名类型 ListNode* 光标;

LinkedList.h 看起来像这样:

#ifndef CLASS_LINKEDLIST_H
#define CLASS_LINKEDLIST_H

// Header files 

#include <iostream>
#include "ListNode.h"

using namespace std;

class LinkedList 
   {
    public:
    LinkedList( int maxSize = 10 );
    LinkedList( const LinkedList& other );
    ~LinkedList();

    private:

       ListNode* head;
       ListNode* cursor;

       int capacity;
       int size;
   };

#endif // ifndef CLASS_LINKEDLIST

ListNode.h 是这样的结构:

#ifndef STRUCT_LISTNODE_H
#define STRUCT_LISTNODE_H

using namespace std;

struct ListNode
   {
     ListNode( int nodeData, ListNode* nextPtr);
     int dataItem;
     ListNode* next;
   };
#endif  // STRUCT_LISTNODE_H

ListNode.cpp 看起来像这样:

#ifndef STRUCT_LISTNODE_H
#define STRUCT_LISTNODE_H

#include "ListNode.h"
#include <iostream>

ListNode:: ListNode(int nodeData, ListNode* nextPtr)
   { 
     dataItem = nodeData;
     next = nextPtr;
   }

#endif // STRUCT_LISTNODE_H

这里是 LinkedList.cpp 的顶部

#ifndef STRUCT_LISTNODE_H
#define STRUCT_LISTNODE_H

// header files
#include "LinkedList.h"

我不能更改 .h 文件,只能更改 .cpp 文件。我知道有一些简单的东西我忘记包括在内,但我似乎无法弄清楚。

提前感谢您的帮助。

【问题讨论】:

  • 为什么LinkedList.cpp 有包含守卫?它是否包含在另一个文件中?
  • 是的,从您的 CPP 文件中删除包含防护。包括守卫通常是写着#ifndef filename_h的行。
  • 这是作业吗,你得到了头文件?如果是这样,他们担心标题中有using namespace std;...标题中的using namespace 是个坏主意。
  • 谢谢,我从 CPP 文件中删除了包含保护,它消除了错误。所以那些只应该放在 .h 文件上?
  • @jake415 是的,因为只有标题才会被其他文件包含在内。守卫只是确保文件不会被包含两次。通常,由于不需要 cpp,因此您不需要警卫。

标签: c++ class struct


【解决方案1】:

放置包含保护,这样如果一个文件最终被多次包含,它只会被使用一次。

当您包含一个文件时,出于所有意图和目的,它被复制粘贴到包含文件中,因此对于编译器的预处理器,ListNode.cpp 看起来像这样:

#ifndef STRUCT_LISTNODE_H
#define STRUCT_LISTNODE_H

#ifndef STRUCT_LISTNODE_H
#define STRUCT_LISTNODE_H

using namespace std;

struct ListNode
   {
     ListNode( int nodeData, ListNode* nextPtr);
     int dataItem;
     ListNode* next;
   };
#endif  // STRUCT_LISTNODE_H
#include <iostream> //contents of iostream go on for pages. Let's skip those, shall we?

ListNode:: ListNode(int nodeData, ListNode* nextPtr)
   { 
     dataItem = nodeData;
     next = nextPtr;
   }

#endif // STRUCT_LISTNODE_H

分解编译器会看到:

#ifndef STRUCT_LISTNODE_H

如果尚未定义 STRUCT_LISTNODE_H,请执行所有操作,直到对应的 #endif

#define STRUCT_LISTNODE_H 

酷。 STRUCT_LISTNODE_H 刚刚被定义。

#ifndef STRUCT_LISTNODE_H

这次STRUCT_LISTNODE_H已经定义好了,所以我们直接跳到对应的endif:

#endif  // STRUCT_LISTNODE_H

没错,头文件几乎被完全丢弃了。所以要编译的是:

#ifndef STRUCT_LISTNODE_H
#define STRUCT_LISTNODE_H

#ifndef STRUCT_LISTNODE_H
#endif  // STRUCT_LISTNODE_H
#include <iostream> //contents of iostream go on for pages. Let's skip those, shall we?

ListNode:: ListNode(int nodeData, ListNode* nextPtr)
   { 
     dataItem = nodeData;
     next = nextPtr;
   }

#endif // STRUCT_LISTNODE_H

没有ListNode定义的迹象。

所以这并不是说 OP 在 cpp 文件中使用了包含保护(并且永远不应包含 cpp 文件,因此不需要包含保护),而是 OP 两次使用了相同的包含保护。

作为公共服务公告,关于using namespace std;的常见警告 那个邪恶的小捷径将整个标准库拉入全局命名空间。这意味着如果您有一个名为reverse 的函数,它现在必须与std::reverse 对抗,您可能不喜欢谁获胜以及这对您的程序执行有何影响。

没关系。您的代码对此很好,但是如果您包含其他人的代码怎么办?现在他们与他们不打算使用的名称发生冲突,并且您收到他们从未见过的奇怪错误消息,并且可能无法帮助您。

谨慎使用它。以 std:: 为前缀

std::cout << "HI!" << std::endl;

或者只将你需要的部分拉入全局命名空间

using std::cout;
using std::endl;

以后

cout << "HI!" << endl;

最重要的是在包含其他所有人的头文件后最后执行此操作,因为您不知道他们将如何响应。但这是你懒惰的问题。做你真糟糕。

这让我们明白了为什么不将using namespace std; 放在标题中。一些可怜的傻瓜包括你的标题来使用你的图书馆。哇!他们继承了你糟糕的编码风格。他们为你的错误受苦。这不酷。

【讨论】:

    猜你喜欢
    • 2012-01-07
    • 1970-01-01
    • 2015-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-05
    • 2014-04-17
    相关资源
    最近更新 更多