0

I'm having an issue where it appears an implementation file is recognizing only the forward declaration of another class, and not its actual declaration. I've tried using various guards with imports and taking out the forward declaration but to no avail.

Class A has a function "decode" which takes one argument of type B that's defined in a separate file. I'd like to keep all .h's and .cpp's as distinct files. Here they are.

A.h:

class B;
class A{
private:
    string sentence;
public:
    A();
    void decode(const B& decoder);
};

B.h:

class B{
private:
    int code[26];
public:
    B();
    int getCode(int index);
};

A.cpp:

#include "A.h"
A::A(){}
double A::decode(const B& decoder){
    B.getCode(1);
    //other things
}

B.cpp:

#include "B.h"

B::B(){}
int B::getCode(int index){};

and the driver:

#include "B.h"
#include "A.h"
using namespace std;
int main(int argc, char* argv[]){
    B myB;
    A myA;
    myA.decode(B);
}

I'm compiling this with g++ -Wall driver.cpp B.cpp A.cpp, but get hit with an error that looks like:

A.cpp:4 error: invalid use of incomplete type 'const class B'

I've looked through a ton of similar threads trying to find the answer, but nothing has worked for me yet. Any ideas?

Ethan
  • 5
  • 5
  • 1
    You need to `#include "B.h"` in A.cpp. – R Sahu Feb 05 '18 at 20:21
  • #include "B.h" at the top of "A.h". Only include "A.h" in main,cpp. Learn to use include-guards. – Jive Dadson Feb 05 '18 at 20:26
  • Possible duplicate of [Resolve build errors due to circular dependency amongst classes](https://stackoverflow.com/questions/625799/resolve-build-errors-due-to-circular-dependency-amongst-classes) –  Feb 05 '18 at 20:29

2 Answers2

2

Since you are using B's member function getCode in your A.cpp file, the forward declaration only will not suffice as it says nothing about B's member functions. The entire B declaration needs to be available. To do that, include the "B.h" header in your A.cpp file:

#include "B.h"

As pointed out in the comments you should also utilize the header guards for A.h and B.h headers.

Ron
  • 14,674
  • 4
  • 34
  • 47
0

Best practice is that every .h file includes everything it needs. That means A.h shall include B.h.

A.h:

#pragma once // Or equivalent include-guard macros
#include "B.h"

class A{
private:
    string sentence;
public:
    A();
    void decode(const B& decoder);
};

B.h:

#ifndef B_h
#define B_h true
class B{
private:
    int code[26];
public:
    B();
    int getCode(int index);
};
#endif 

A.cpp:

#include "A.h"
A::A(){}
double A::decode(const B& decoder){
    B.getCode(1);
    //other things
}

B.cpp:

#include "B.h"

B::B(){}
int B::getCode(int index){};

and the driver:

#include "A.h"

void main(){
    B myB;
    A myA;
    myA.decode(B);
}
Jive Dadson
  • 16,680
  • 9
  • 52
  • 65