or.nomore or.nomore - 4 months ago 57
C++ Question

Class name does not name a type in C++

I just started programming in C++, and I've tried to create 2 classes where one will contain the other.

File

A.h
:

#ifndef _A_h
#define _A_h

class A{
public:
A(int id);
private:
int _id;
B _b; // HERE I GET A COMPILATION ERROR: B does not name a type
};

#endif


File
A.cpp
:

#include "A.h"
#include "B.h"
#include <cstdio>

A::A(int id): _id(id), _b(){
printf("hello\n the id is: %d\n", _id);
}


File
B.h
:

#ifndef _B_h
#define _B_h

class B{
public:
B();
};
#endif


File
B.cpp
:

#include "B.h"
#include <cstdio>

B::B(){
printf("this is hello from B\n");
}


I first compile the B class and then the A class, but then I get the error message:


A.h:9: error: ‘B’ does not name a type


How do I fix this problem?

Answer

The preprocessor inserts the contents of the files A.h and B.h exactly where the include statement occurs (this is really just copy/paste). When the compiler then parses A.cpp, it finds the declaration of class A before it knows about class B. This causes the error you see. There are two ways to solve this:

  1. Include B.h in A.h. It is generally a good idea to include header files in the files where they are needed. If you rely on indirect inclusion though another header, or a special order of includes in the compilation unit (cpp-file), this will only confuse you and others as the project gets bigger.
  2. If you use member variable of type B in class A, the compiler needs to know the exact and complete declaration of B, because it needs to create the memory-layout for A. If, on the other hand, you were using a pointer or reference to B, then a forward declaration would suffice, because the memory the compiler needs to reserve for a pointer or reference is independent of the class definition. This would look like this:

    class B; // forward declaration        
    class A {
    public:
        A(int id);
    private:
        int _id;
        B & _b;
    };
    

    This is very useful to avoid circular dependencies among headers.

I hope this helps.