【问题标题】:Error: class name does not name a type in C++错误:类名没有在 C++ 中命名类型
【发布时间】:2020-09-27 05:15:38
【问题描述】:

我知道这个问题已经被问过很多次了,但我已经尝试了一些建议,例如检查我的拼写、确保我包含了头文件、大写等,但我仍然遇到同样的错误并且可以不知道是什么触发了它。

当我尝试使用 g++ -c Customer.h 编译 Student.h 时,我收到错误“Student”没有在“Student student;”行上命名类型对于 Login.h,我不知道为什么。任何人都可以尝试查明是什么原因造成的吗?这个变量应该代表这个登录ID/帐户的学生,它应该是一个指向学生对象的指针。

同样,当我尝试编译 Login.h 时,我得到错误 'Login' has not been declared in Customer.h for bool addAcct(Login*) 以及错误 'Login' does not have a type for登录* 登录[MAX_LOGINS]。

任何帮助将不胜感激!

学生.h:

#ifndef STUDENT_H
#define STUDENT_H
#define MAX_LOGINS 4
#include <string>
#include "Login.h" 
using namespace std;

class Student{
    public:
        Student(int = 0, string = ""); 
        int getId();
        bool addAcct(Login*);
        void print();
    private:
        int id;
        string name;
        Login* logins[MAX_LOGINS];
        int numberOfLogins;
};
#endif

登录.h

#ifndef LOGIN_H
#define LOGIN_H
#include <string>
#include "Student.h"
using namespace std;

class Login{
    public:
        Login(int = 0, float = 0); 
        int getNumber();
        void setStudent();
        void print();
    private:
        int number;
        Student student;
};
#endif

【问题讨论】:

  • 循环依赖,login.h 包含 student.h,而 student.h 又包含 login.h。你的两个类都需要先声明另一个类,这显然是不可能的情况。您需要研究前向声明
  • 特别是由于 Student 仅使用 Login 作为指针,您可以从 student.h 中删除 #include "login.h" 并将其替换为前向声明 class Login;
  • 我的情况是两个类之间都有双向关联,并且每个类都有另一个类的实例。我会研究更多关于循环依赖问题的,谢谢!
  • 阅读 good C++ programming book 和您的 C++ 编译器(例如 GCC...)和调试器(例如 GDB...)的文档。使用g++ -Wall -Wextra -g编译

标签: c++ class pointers compiler-errors


【解决方案1】:

这里的问题是循环依赖(如 cmets 中所指出的),问题在于处理器基本上将 #include 语句作为顺序文本插入处理。

例如,当预处理器遇到#include "student.h"时,它会一步一步地走:

#ifndef STUDENT_H  // <--- header guard not defined at this point, ok to proceed
#define STUDENT_H  // <--- define header guard first thing in order to prevent recursive includes
#define MAX_LOGINS 4
#include <string>
#include "Login.h"  --->  #ifndef LOGIN_H
                          #define LOGIN_H
                          #include <string>
                          #include "Student.h"  --->  #ifndef STUDENT_H
                                                      // entire body of student.h is skipped over
                                                      // because STUDENT_H header guard is defined
                          using namespace std;  <---  // so processing continues here

                          class Login{
                          // ...
                          Student student;   // <--- error because class Student is not defined
                          };

解决方案是转发声明不需要完整定义的类型,而不是 #include'ing 相应的标头。

在这种情况下,class Login 有一个成员 Student student;,这需要完全定义 class Student,所以 login.h 实际上必须是 #include "student.h"

但是,class Student 只携带指向Login 的指针Login* logins[MAX_LOGINS]; 数组,并且指针不需要类的完整定义,而只需要类型的前向声明。因此Student.h可以修改为转发声明class Login,这样就去掉了循环头依赖,允许代码编译。

// #include "Login.h"  // <--- full header not required

class Login;           // <--- forward declaration is sufficient

【讨论】:

    猜你喜欢
    • 2015-12-01
    • 1970-01-01
    • 2021-02-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-10
    • 1970-01-01
    • 2011-12-10
    • 2011-01-09
    相关资源
    最近更新 更多