Error: class name does not name a type in C++

Viewed 1263

I'm aware this question has been asked numerous times but I've tried several suggestions such as checking my spelling, making sure I included the header files, capitalization, etc, but I'm still getting the same error and can't figure out what's triggering it.

When I try to compile Student.h using g++ -c Customer.h I get the error 'Student' does not name a type on the line 'Student student;' for Login.h and I have no idea why. Can anyone try to pinpoint what's causing it? This variable is supposed to represent the student of this login id/account which is supposed to be a pointer to a Student object.

Likewise, when I try to compile Login.h, I get the error 'Login' has not been declared in Customer.h for bool addAcct(Login*) as well as the error 'Login' does not have a type for Login* logins[MAX_LOGINS].

Any help would be appreciated!

Student.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

Login.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
1 Answers

Issue here is the circular dependency (as pointed out in the comments), and the problem with that is the processor essentially handles #include statements as sequential text insertions.

For example, when the preprocessor encounters #include "student.h", it goes step by step like:

#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
                          };

The solution is to forward declare types which do not require a full definition, instead of #include'ing the respective header.

In this case, class Login has a member Student student; which requires class Student to be fully defined, so login.h must in fact #include "student.h".

However, class Student only carries the Login* logins[MAX_LOGINS]; array of pointers to Login, and a pointer does not require a full definition of the class, but just a forward declaration of the type. Therefore Student.h can be modified to forward declare class Login instead, which removes the circular header dependency and allows the code to compile.

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

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