Cyclic dependency in Eclipse CDT - c++

I know this matter doesn't get enough attention because it's not meet often but I want to clarify it.
Say I have 3 files:
A.h
#ifndef A_h
#define A_h
#include "B.h"
class A {
A();
virtual ~A();
bool someFunc(B& b);
};
#endif
B.h
#ifndef B_h
#define B_h
#include "A.h"
class B {
B();
virtual ~B();
bool someFunc(A& a);
};
#endif
and main.cpp
#include "A.h"
#include "B.h"
int main() { return 0; }
without the protection (#ifndef X_h #define X_h) there is a Cyclic dependency. Adding the protection should solve the problem but when the code is compiled first main.cpp tries to include a.h which tries to include b.h before a is declared and that returns an error. If we change the code to:
A.h
#ifndef A_h
#define A_h
class A {
A();
virtual ~A();
#include "B.h"
bool someFunc(B& b);
};
#endif
B.h
#ifndef B_h
#define B_h
class B {
B();
virtual ~B();
#include "A.h"
bool someFunc(A& a);
};
#endif
Now the Cyclic dependency is solved but and the code compiles without error but still Eclipse returns an error: "Type 'B' could not be resolved" in A.h so you need to add surpress to both A.h and B.h where the other one is used. I want to know if there is another way to solve the Cyclic dependency without Eclipse returning an error and how should the code look if we have more than two classes (A includes B, C and D; B includes A, C, D ...)

As long as you don't actually use instance of class B in class A and the other way around, and only declare functions taking pointers or references, you can get away without including at all, and only declare the classes:
In file A.h
#ifndef A_h
#define A_h
class B; // Declare class B
class A {
A();
virtual ~A();
bool someFunc(B& b);
};
#endif
and in B.h
#ifndef B_h
#define B_h
class A; //Declare class A
class B {
B();
virtual ~B();
bool someFunc(A& a);
};
#endif
In the source files where the functions are defined (implemented) you of course needs to include both files.

Related

Is it possible to have restricted access to included class?

I have a class say A in A.h file and class B: public A in B.h file.
A.h file
#ifndef A_H
#define A_H
class A
{
public:
void foo {}
};
#endif
B.h file
#ifndef B_H
#define B_H
#include "A.h"
class B: public A
{
...
};
#endif
Is there a way to include B but not to have access to A until I include A.h?
Like this
#include "B.h"
main() {
B* b = new B(); //OK
b->foo(); //OK
A* a = new A(); //Error
a->foo(); //Error
}
No. B.h depends on the definition of A, so there is no way to include B.h without including the definition of A. And there is no way of getting around that dependency if B must be defined in B.h and if B must inherit A.
You can make the creation of separate A into an error by changing A to be an abstract type. But that would remain an error even if A.h was included separately.

C++ nested class instances

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
}

C++ How to avoid from cyclic inclusion? [duplicate]

This question already has answers here:
forward declarations
(3 answers)
Closed 7 years ago.
I have two classes.
First A.h
#ifndef A_H
#define A_H
#include "B.h"
class A
{
public:
A(B* pair) :myPair(pair){};
void checkPair();
private:
B* myPair;
};
void A::checkPair()
{
myPair->checkPair();
}
#endif
Second B.h
#ifndef B_H
#define B_H
#include "A.h"
class B
{
public:
B(A* pair) :myPair(pair){};
void checkPair();
private:
A* myPair;
};
void B::checkPair()
{
myPair->checkPair();
}
#endif
The Compiler tells me that he can't identify class A in B.h file.
Is there any solutions for cyclic inclusion problems like this?
In A.h file instead of including B.h use forward declaration:
class B;

C++ Forward Declaration and Inheritence

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.

In C++, I want two classes to access each other

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.