How can I use a member function of a forward declared class?

Viewed 2937

I have 2 classes A and B and the 4 following files:

A.h

#ifndef A_H
#define A_H

#include "B.h"
class A {
public:
    A();
    int functionA();
    B objectB;
};

#endif //A_H

B.h

#ifndef B_H
#define B_H

class A;
class B {
public:
    B();
    int functionB();
    A * objectA;
};

#endif //B_H

A.cpp

#include "A.h"
A::A(){}
int A::functionA() {
    return 11;
}

B.cpp

#include "B.h"
B::B(){}
int B::functionB() {
    return objectA->functionA();
}

Now I compile using the line: g++ A.cpp B.cpp -Wall -Wextra -O2 -march=native -std=gnu++1z

I get this error:

B.cpp: In member function 'int B::functionB()':
B.cpp:4:19: error: invalid use of incomplete type 'class A'
     return objectA->functionA();
                   ^
In file included from B.cpp:1:0:
B.h:1:7: note: forward declaration of 'class A'
 class A;
       ^

How can I use a member class of the function forward declared here?

3 Answers

Look at what is included when compiling B.cpp, you have a forward declaration of class A but not the real definition. So in B.cpp on line 4, functionA is unknown to the compiler therefore your type is incomplete.

You should include A.h in B.cpp.

In A.cpp , Include both A.h and B.h
In B.cpp, Include both B.h and A.h.

It works because:

  1. We don't have cyclic inclusion (a header file which includes another header file, which includes the original)
  2. Each class implementation "sees" how the other class looks like, but not how it's implemented, we don't break "separation of interface from implementation" rule. there are some cases where we don't do that, but for most cases, it's valid.

The thumb rule (only a thumb rule!) is to include the class header in every .cpp file which uses that class. so if foo.cpp uses the class bar, and class bar interface is in bar.h, then foo.cpp should include bar.h. There are some specific cases we don't follow that rule, but for the most cases, it's valid.

Using members of a class with only a forward declaration is impossible.

If your code uses a member function, the class should be fully declared, because the compiler needs to check that the member function with this name actually exists.

Related