I'm having an issue wrapping my head around circular include problems and in particular that I'm currently dealing with. I have two classes/structs each in their own files. Class A has an inner class and class B has a member of that type. I need to use instances of B within A which would be ok if they were delcared in the same file but since they're not how can I make this work?
A.h
#pragma once
#include "B.h"
class A
{
public:
class Inner{};
B getNewB() { return B{}; }
};
B.h
#pragma once
#include "A.h"
struct B
{
A::Inner inner;
};
A.h:
#pragma once
#include "innerA.h"
struct B;
class A
{
public:
B getNewB();
friend class InnerA;
};
A.cpp
#include "A.h"
#include "B.h"
B A::getNewB() { return B{}; }
B.h
#pragma once
#include "innerA.h"
struct B
{
InnerA inner;
};
B.cpp
#include "B.h"
InnerA.h
#pragma once
class InnerA
{
};
InnerA.cpp
#include "innerA.h"
I moved A::Inner to another class and add friend relation (You can add bidirectional, use same trick as above I with struct declaration)
Related
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?
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.
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);
}
What I have is 2 classes:
A.h:
#include "B.h"
class A
{
vector<B*> arr;
void Update(int32 id){...};
}
B.h
#include "A.h"
class B
{
int32 id;
A* parent;
void OnRemove()
{
...
parent->Update(id);
}
}
With that logic everything must work fine as expected.
But it won't because of loop include: A.h including B.h and B.h including A.h
The question is how to make it working with that structure of code or other.
Main feature that should exist is to call event in A object which is holding B object.
Every help would be appreciated.
Forward declare class A; in B.h and class B; in A.h
You should then move the implementation of onRemove() to B.cpp and include A.h here.
Also don't forget your include guards. Example:
#ifndef _A_H_
#define _A_H_
class B;
class A {
};
#endif
The include guards could also be replaced by #pragma once at the beginning of the header, this is a little less verbose.
Edit
To be complete:
// A.h
#pragma once
#include <vector>
class B;
class A {
std::vector<B*> arr;
public:
void Update(int32 id);
};
// A.cpp
#include "A.h"
// possibly #include "B.h" if necessary
void A::Update(int32 id) {
// impl ...
}
// B.h
#pragma once
class A;
class B
{
int32 id;
A* parent;
public:
void OnRemove();
};
// B.cpp
#include "B.h"
#include "A.h"
void B::OnRemove() {
parent->Update(id);
}
Well, something like this...
the usual way is to provide guarding macros to prevent recursion and move definition of functions in a separate file if needed:
a.h
#ifndef _A_H_
#define _A_H_
#include "B.h"
class A
{
vector<B*> arr;
void Update(int32 id){...};
}
#endif
...
c.cpp (if needed)
#include <a.h>
#include <b.h>
void B::onRemove() {
blahblahblah
}
Can you figure out how to solve this circular inclusion problem?
C extends B and B includes A. A includes C. Every forward declaration I tried hasn't worked.
Errors
Error 1 error C2504: 'B' : base class undefined
Error 2 error C3668: 'C::c' : method with override specifier 'override' did not override any base class methods
File A.h:
#pragma once
#include "C.h"
struct A
{
A();
C c;
};
File B.h:
#pragma once
#include "A.h"
struct A;
struct B
{
virtual void c() = 0;
A* a;
};
File C.h:
#pragma once
#include "B.h"
struct B;
struct C : public B
{
void c() override;
};
The solution is always the same and it looks like you were on the right track. However, you're not using forward declartions correctly. There should be many examples of how to do this for example here.
B.h
// Why are including "A.h" here, this is causing your circular include
// issue, it needs to be moved to your implementation (e.g., "B.cpp")
#include "A.h"
struct A; // Forward declaration, good
struct B
{
virtual void c() = 0;
A* a; // A pointer only requires the above forward declartion
};
C.h
#include "B.h" // Necessary since you're extending `B`
struct B; // This forward declaration is superfluous and should be removed
struct C : public B
{
void c() override;
};
I have a situation as such
A.h
#ifndef _CLASSA
#define _CLASSA
class B;
class A {
virtual void addTo(B*) {}
};
#endif
B.h
#ifndef _CLASSB
#define _CLASSB
#include "A.h"
class B : public A {
B();
void addTo(B* b) {
// blah blah blah
}
};
#endif
B.cpp
#include "B.h"
B::B() : A() {}
main.cpp
#include "B.h"
int main() {
A* b = new B();
B* d = new B();
b->addTo(d);
}
The project won't compile. If I forward declare B in the A header, the compiler complains about the expectation of a class in B.h. If I include the B.h header in A.h, the compiler can't resolve the base class. Is this possible?
Yes, include A.h in B.h and forward declare B in A.h.
If I forward declare B in the A header, the compiler complains about the expectation of a class in B.h
The way you have the code now it should work. But I suspect you're actually using B inside the method addTo, in which case a forward declaration is not enough. You need to separate the implementation to an implementation file and include B there.
EDIT: As DeadMg pointed out, class B : class A { isn't valid syntax, you probably want class B : A or class B : public A.
I have two classes, class A and class B.
A.h -> A.cpp
B.h -> B.cpp
And then, I set B as a member in class A. Then, class A can access class B by
#include <B.h>
But, how can I get the pointer of class A in class B and access the public member of class A?
I found some information about on the internet: a Cross-class. They said you can make it by setting the class B as a nested class in class A.
Do you have any other advice?
sorry.
myCode: as follow..
class A:
#ifndef A
#define A
#include "B.h"
class A
{
public:
A() {
b = new B(this);
}
private:
B* b;
};
#endif
#ifndef B
#define B
#include"A.h"
class B
{
public:
B(A* parent = 0) {
this->parent = parent;
}
private:
A* parent;
};
#endif
Just use forward declaration. Like:
A.h:
#ifndef A_h
#define A_h
class B; // B forward-declaration
class A // A definition
{
public:
B * pb; // legal, we don't need B's definition to declare a pointer to B
B b; // illegal! B is an incomplete type here
void method();
};
#endif
B.h:
#ifndef B_h
#define B_h
#include "A.h" // including definition of A
class B // definition of B
{
public:
A * pa; // legal, pointer is always a pointer
A a; // legal too, since we've included A's *definition* already
void method();
};
#endif
A.cpp
#inlude "A.h"
#incude "B.h"
A::method()
{
pb->method(); // we've included the definition of B already,
// and now we can access its members via the pointer.
}
B.cpp
#inlude "A.h"
#incude "B.h"
B::method()
{
pa->method(); // we've included the definition of A already
a.method(); // ...or like this, if we want B to own an instance of A,
// rather than just refer to it by a pointer.
}
Knowing that B is a class is enough for compiler to define pointer to B, whatever B is. Of course, both .cpp files should include A.h and B.h to be able to access class members.