C++: passing the this pointer to another class - c++

I'm new to C++ but I do have some experience in Java.
While coding, I stumbled across an error that confused me.
Here's my code (simplified, but the errors are the same):
A.h:
#pragma once
#include "B.h"
class A
{
public:
A();
void foo();
void sayHello();
B b;
};
A.cpp:
#include "A.h"
#include <iostream>
A::A() {}
void A::foo() {
b.bar(this);
}
void A::sayHello() {
std::cout << "Hello" << std::endl;
}
B.h:
#pragma once
#include "A.h"
class B
{
public:
B();
void bar(A *a);
};
B.cpp:
#include "B.h"
B::B(){}
void B::bar(A *a) {
a->sayHello();
}
I want to pass a pointer of the a object to the bar function in B, so that I'll be able to modify and access a's fields in bar. Strangely, I get these errors when I call foo through an instance of A from another class:
1>------ Build started: Project: Test, Configuration: Debug Win32 ------
1> main.cpp
1>d:\stuff\visual studio 2015\projects\test\test\b.h(7): error C2061: syntax error: identifier 'A'
1> B.cpp
1>d:\stuff\visual studio 2015\projects\test\test\a.h(9): error C3646: 'b': unknown override specifier
1>d:\stuff\visual studio 2015\projects\test\test\a.h(9): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1> A.cpp
1>d:\stuff\visual studio 2015\projects\test\test\b.h(7): error C2061: syntax error: identifier 'A'
1>d:\stuff\visual studio 2015\projects\test\test\a.cpp(5): error C2660: 'B::bar': function does not take 1 arguments
1> Generating Code...
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
The code works fine if I don't include A.h in B.h and I don't pass anything to the bar function.
I tried to google what could cause these errors but I wasn't able to resolve the issue by myself becuase I don't understand what's causing these errors. What am I doing wrong?

In the header file of A.h, you have:
#include "B.h"
In the header file of B.h, you have:
#include "A.h"
You have a circular include where the definition of A and B depends on each other.
A simple solution is to use forward declaration in definition of class B:
Replace the line #include "A.h" in file B.h with class B;
Add #include "A.h" at the beginning of B.cpp
Notice however, you cannot use forward declaration for class A, the reason is that you have a value b of class B as a member variable of class A:
#pragma once
#include "B.h"
class A
{
public:
A();
void foo();
void sayHello();
B b; /// I mean this line here more specifically
};
The compiler need to know the the definition of class B in order to determine the correct size for class A. That's why you have to put the #include "B.h" at the very beginning of A.h.

Let's take a look at B.cpp and watch what happens with the includes:
#include "B.h"
B::B(){}
void B::bar(A *a) {
a->sayHello();
}
With B.h pasted in place of the include we get:
#include "A.h"
class B
{
public:
B();
void bar(A *a);
};
B::B(){}
void B::bar(A *a) {
a->sayHello();
}
And then placing A.h in place of its include:
#include "B.h"
class A
{
public:
A();
void foo();
void sayHello();
B b;
};
class B
{
public:
B();
void bar(A *a);
};
B::B(){}
void B::bar(A *a) {
a->sayHello();
}
And here we stop because pragma once prevents re-inclusion of B.h
We can see that in class A's definition we have B b;, but class B is not yet defined. Kaboom. A cannot be defined without B and B is not defined yet.
A must have the size of B to satisfy B b;, so it requires the full definition of B. B only needs to know A exists because it only needs a pointer to A to satisfy void bar(A *a);. So...
A.h
#pragma once
#include "B.h"
class A
{
public:
A();
void foo();
void sayHello();
B b;
};
A.cpp
#include "A.h"
#include <iostream>
A::A() {}
void A::foo() {
b.bar(this);
}
void A::sayHello() {
std::cout << "Hello" << std::endl;
}
B.h
#pragma once
class A; // forward definition of class A
class B
{
public:
B();
void bar(A *a);
};
B.cpp
#include "A.h"
B::B(){}
void B::bar(A *a) {
a->sayHello();
}

Both headers are referencing each other. Only one can ever actually be evaluated first by the compiler and that one cannot resolve the reference to the class in the other header. It's not obvious by the error, but the "once" #pragma is making one of the header includes not happen as you expect.
If the B.h header file does not need to know implementation details about the A class, which it does not in this case, then do not include the A.h file in B.h. Instead, change your function declaration of bar() to look like this:
bar( class A *a );
The compiler can build code from this that passes a pointer to an A object without knowing anything about what is inside of A. It doesn't need the A.h header.
Then include the A.h header file after the B.h header file in B.cpp.
I tested this and it works for me.

Do these changes:
B.h: - Forward declare A
#pragma once
// #include "A.h"
class A;
//^^^^^^
class B {
public:
B();
void bar(A *a);
};
B.cpp: #include "A.h"
//#include "B.h"
#include "A.h"
//^^^^^^^^^^^^
B::B(){}
void B::bar(A *a) {
a->sayHello();
}
That's it.

Related

C++ include loop. Can't use forward declarations

I want to do something like this, running from main():
Main.cpp
#include "A.h"
#include "B.h"
int main(){
A* a = new A();
B* b = new B(a);
b->render();
return 0;
A.h
class B;
class A {
public:
void renderObject(B* b);
}
A.cpp
#include "A.h"
void renderObject(B* b) {
int* data = b->data;
//do something with data
B.h
class A;
class B {
public:
A* a;
B(A* a);
int* data;
void render();
}
B.cpp
#include "B.h"
B(A* a) {
this->a = a;
//something that write stuff to data.
}
void render() {
a->renderObject(this);
}
Is this kind of coding possible? What can I do so that both can reference to both?
For this line in A.cpp you need more than "it is a class", the information provided by a forward declaration.
I.e. in this file you need an additional
#include "B.h"
Similar for B.cpp, it needs to include A.h for the contained code.
(Thanks, Scheff.)
And, at least if only looking at the shown code, you do not really need to include A.h in A.cpp. This already changes if you add the seemingly missing A:: and the rest of the actual file very likely needs it.

Default constructor not called if classes devided into separate files

UPDATE:
Now I have this, and it does not compile:
A.h:
#ifndef A_H
#define A_H
class A {
private:
int foo;
public:
A();
int getfoo();
};
#endif
A.cpp:
#include "A.h"
A::A() {
foo = 5;
}
int A::getfoo(){
return foo;
}
B.h:
#ifndef B_H
#define B_H
class B {
private:
A myA;
public:
B();
int getAvalue();
};
#endif
B.cpp:
#include "A.h"
#include "B.h"
int B::getAvalue(){
return myA.getfoo();
}
Errors:
b.h line 6: C2146: missing ';' before identifier 'myA'
b.h line 6: C4430: missing type specifier - int assumed
b.h line 6: C4430: missing type specifier - int assumed
END UPDATE
I have written 2 classes in different cpp and header files: class A and class B.
Class B uses class A as a private variable and the default constructor of class A is never called.
Here is my code:
A.h:
class A {
public:
A();
int getfoo();
};
A.cpp:
class A {
private:
int foo;
public:
A();
int getfoo();
};
A::A() {
foo = 5;
}
int A::getfoo(){
return foo;
}
B.h:
class B {
public:
int getAvalue();
};
B.cpp:
#include "A.h"
class B {
private:
A myA;
public:
int getAvalue();
};
int B::getAvalue(){
return myA.getfoo();
}
classtest.cpp:
#include "stdafx.h"
#include <iostream>
#include "B.h"
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
B stackB;
cout << stackB.getAvalue() << endl;
B* storeB = new B();
cout << storeB->getAvalue() << endl;
cin.get();
return 0;
}
The output is never 5 and the breakpoint inside the constructor A::A() is never triggered. It doesn't matter if I use B globally or locally. This sample works totally fine if I put the classes and functions in one single file.
If I add an empty default constructor to class B, the default constructor of class A gets called, but then Visual Studio 2008 complains about stack corruption around variable stackB.
What am I doing wrong?
Just with this class alone:
A.h:
class A {
public:
A();
int getfoo();
};
A.cpp:
class A {
private:
int foo;
public:
A();
int getfoo();
};
A::A() {
foo = 5;
}
int A::getfoo() {
return foo;
}
You are declaring class A in A.h.
Then in your implementation(cpp) file, you are then again declaring class A.
You are also forgetting to include A.h in A.cpp. If you included the header into the cpp; the compiler would of thrown out errors telling you what was wrong. You are also missing either header guards, or the pragma directive.
Your class should look like this:
A.h
#ifndef A_H
#define A_H
class A {
private:
int foo;
public:
A();
int getFoo() const; // const to return member and prevents modification
};
#endif // !A_H
A.cpp
#include "A.h" // you forgot to include the header
A::A() : // class constructor using it's member initializer list
foo( 5 ) {
}
int A::getFoo() const {
return foo;
}
Now once you fix your class, then working on class B should not be a problem. However there is one thing to be careful of when including a header file of one class into another; you can end up with circular includes. The best way to prevent that is to use a class prototype in the header and include its header in the containing class's cpp file. There are some cases where a class proto type will not work, but I'll leave that up to you to do the research.
How to use Class Prototype in C++
Class B might look like this:
B.h
#ifndef B_H
#define B_H
// #include "A.h" // uncomment this if prototype below doesn't work.
class A; // class prototype may not work in all cases;
// If the above prototype does not work; comment it out
// and replace it with #include "A.h".
class B {
private:
A myA;
public:
B(); // remove default
int getAValue() const;
};
#endif // !B_H
B.cpp
#include "B.h"
#include "A.h" // If class A's prototype in the header does not work
// then comment this out and place it in this class B's header by
// replacing it with the prototype.
B::B() {} // default constructor (should make this complete type)
int B::getAValue() const {
return myA.getFoo();
}
And this should help to fix your problems. If using the class prototype does not work in the header because in some cases it may not; you can remove the prototype declaration from the header and replace it with the include directive of that class and remove its include from the cpp file.

Implementation File will only recognize forward declaration of other class

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);
}

Class Error C2146 syntax error: missing ';' before identifier 'pTrigger' [duplicate]

I often find myself in a situation where I am facing multiple compilation/linker errors in a C++ project due to some bad design decisions (made by someone else :) ) which lead to circular dependencies between C++ classes in different header files (can happen also in the same file). But fortunately(?) this doesn't happen often enough for me to remember the solution to this problem for the next time it happens again.
So for the purposes of easy recall in the future I am going to post a representative problem and a solution along with it. Better solutions are of-course welcome.
A.h
class B;
class A
{
int _val;
B *_b;
public:
A(int val)
:_val(val)
{
}
void SetB(B *b)
{
_b = b;
_b->Print(); // COMPILER ERROR: C2027: use of undefined type 'B'
}
void Print()
{
cout<<"Type:A val="<<_val<<endl;
}
};
B.h
#include "A.h"
class B
{
double _val;
A* _a;
public:
B(double val)
:_val(val)
{
}
void SetA(A *a)
{
_a = a;
_a->Print();
}
void Print()
{
cout<<"Type:B val="<<_val<<endl;
}
};
main.cpp
#include "B.h"
#include <iostream>
int main(int argc, char* argv[])
{
A a(10);
B b(3.14);
a.Print();
a.SetB(&b);
b.Print();
b.SetA(&a);
return 0;
}
The way to think about this is to "think like a compiler".
Imagine you are writing a compiler. And you see code like this.
// file: A.h
class A {
B _b;
};
// file: B.h
class B {
A _a;
};
// file main.cc
#include "A.h"
#include "B.h"
int main(...) {
A a;
}
When you are compiling the .cc file (remember that the .cc and not the .h is the unit of compilation), you need to allocate space for object A. So, well, how much space then? Enough to store B! What's the size of B then? Enough to store A! Oops.
Clearly a circular reference that you must break.
You can break it by allowing the compiler to instead reserve as much space as it knows about upfront - pointers and references, for example, will always be 32 or 64 bits (depending on the architecture) and so if you replaced (either one) by a pointer or reference, things would be great. Let's say we replace in A:
// file: A.h
class A {
// both these are fine, so are various const versions of the same.
B& _b_ref;
B* _b_ptr;
};
Now things are better. Somewhat. main() still says:
// file: main.cc
#include "A.h" // <-- Houston, we have a problem
#include, for all extents and purposes (if you take the preprocessor out) just copies the file into the .cc. So really, the .cc looks like:
// file: partially_pre_processed_main.cc
class A {
B& _b_ref;
B* _b_ptr;
};
#include "B.h"
int main (...) {
A a;
}
You can see why the compiler can't deal with this - it has no idea what B is - it has never even seen the symbol before.
So let's tell the compiler about B. This is known as a forward declaration, and is discussed further in this answer.
// main.cc
class B;
#include "A.h"
#include "B.h"
int main (...) {
A a;
}
This works. It is not great. But at this point you should have an understanding of the circular reference problem and what we did to "fix" it, albeit the fix is bad.
The reason this fix is bad is because the next person to #include "A.h" will have to declare B before they can use it and will get a terrible #include error. So let's move the declaration into A.h itself.
// file: A.h
class B;
class A {
B* _b; // or any of the other variants.
};
And in B.h, at this point, you can just #include "A.h" directly.
// file: B.h
#include "A.h"
class B {
// note that this is cool because the compiler knows by this time
// how much space A will need.
A _a;
}
HTH.
You can avoid compilation errors if you remove the method definitions from the header files and let the classes contain only the method declarations and variable declarations/definitions. The method definitions should be placed in a .cpp file (just like a best practice guideline says).
The down side of the following solution is (assuming that you had placed the methods in the header file to inline them) that the methods are no longer inlined by the compiler and trying to use the inline keyword produces linker errors.
//A.h
#ifndef A_H
#define A_H
class B;
class A
{
int _val;
B* _b;
public:
A(int val);
void SetB(B *b);
void Print();
};
#endif
//B.h
#ifndef B_H
#define B_H
class A;
class B
{
double _val;
A* _a;
public:
B(double val);
void SetA(A *a);
void Print();
};
#endif
//A.cpp
#include "A.h"
#include "B.h"
#include <iostream>
using namespace std;
A::A(int val)
:_val(val)
{
}
void A::SetB(B *b)
{
_b = b;
cout<<"Inside SetB()"<<endl;
_b->Print();
}
void A::Print()
{
cout<<"Type:A val="<<_val<<endl;
}
//B.cpp
#include "B.h"
#include "A.h"
#include <iostream>
using namespace std;
B::B(double val)
:_val(val)
{
}
void B::SetA(A *a)
{
_a = a;
cout<<"Inside SetA()"<<endl;
_a->Print();
}
void B::Print()
{
cout<<"Type:B val="<<_val<<endl;
}
//main.cpp
#include "A.h"
#include "B.h"
int main(int argc, char* argv[])
{
A a(10);
B b(3.14);
a.Print();
a.SetB(&b);
b.Print();
b.SetA(&a);
return 0;
}
I'm late answering this, but there's not one reasonable answer to date, despite being a popular question with highly upvoted answers....
Best practice: forward declaration headers
As illustrated by the Standard library's <iosfwd> header, the proper way to provide forward declarations for others is to have a forward declaration header. For example:
a.fwd.h:
#pragma once
class A;
a.h:
#pragma once
#include "a.fwd.h"
#include "b.fwd.h"
class A
{
public:
void f(B*);
};
b.fwd.h:
#pragma once
class B;
b.h:
#pragma once
#include "b.fwd.h"
#include "a.fwd.h"
class B
{
public:
void f(A*);
};
The maintainers of the A and B libraries should each be responsible for keeping their forward declaration headers in sync with their headers and implementation files, so - for example - if the maintainer of "B" comes along and rewrites the code to be...
b.fwd.h:
template <typename T> class Basic_B;
typedef Basic_B<char> B;
b.h:
template <typename T>
class Basic_B
{
...class definition...
};
typedef Basic_B<char> B;
...then recompilation of the code for "A" will be triggered by the changes to the included b.fwd.h and should complete cleanly.
Poor but common practice: forward declare stuff in other libs
Say - instead of using a forward declaration header as explained above - code in a.h or a.cc instead forward-declares class B; itself:
if a.h or a.cc did include b.h later:
compilation of A will terminate with an error once it gets to the conflicting declaration/definition of B (i.e. the above change to B broke A and any other clients abusing forward declarations, instead of working transparently).
otherwise (if A didn't eventually include b.h - possible if A just stores/passes around Bs by pointer and/or reference)
build tools relying on #include analysis and changed file timestamps won't rebuild A (and its further-dependent code) after the change to B, causing errors at link time or run time. If B is distributed as a runtime loaded DLL, code in "A" may fail to find the differently-mangled symbols at runtime, which may or may not be handled well enough to trigger orderly shutdown or acceptably reduced functionality.
If A's code has template specialisations / "traits" for the old B, they won't take effect.
Things to remember:
This won't work if class A has an object of class B as a member or vice versa.
Forward declaration is way to go.
Order of declaration matters (which is why you are moving out the definitions).
If both classes call functions of the other, you have to move the definitions out.
Read the FAQ:
How can I create two classes that both know about each other?
What special considerations are needed when forward declarations are used with member objects?
What special considerations are needed when forward declarations are used with inline functions?
I once solved this kind of problem by moving all inlines after the class definition and putting the #include for the other classes just before the inlines in the header file. This way one make sure all definitions+inlines are set prior the inlines are parsed.
Doing like this makes it possible to still have a bunch of inlines in both(or multiple) header files. But it's necessary to have include guards.
Like this
// File: A.h
#ifndef __A_H__
#define __A_H__
class B;
class A
{
int _val;
B *_b;
public:
A(int val);
void SetB(B *b);
void Print();
};
// Including class B for inline usage here
#include "B.h"
inline A::A(int val) : _val(val)
{
}
inline void A::SetB(B *b)
{
_b = b;
_b->Print();
}
inline void A::Print()
{
cout<<"Type:A val="<<_val<<endl;
}
#endif /* __A_H__ */
...and doing the same in B.h
I've written a post about this once: Resolving circular dependencies in c++
The basic technique is to decouple the classes using interfaces. So in your case:
//Printer.h
class Printer {
public:
virtual Print() = 0;
}
//A.h
#include "Printer.h"
class A: public Printer
{
int _val;
Printer *_b;
public:
A(int val)
:_val(val)
{
}
void SetB(Printer *b)
{
_b = b;
_b->Print();
}
void Print()
{
cout<<"Type:A val="<<_val<<endl;
}
};
//B.h
#include "Printer.h"
class B: public Printer
{
double _val;
Printer* _a;
public:
B(double val)
:_val(val)
{
}
void SetA(Printer *a)
{
_a = a;
_a->Print();
}
void Print()
{
cout<<"Type:B val="<<_val<<endl;
}
};
//main.cpp
#include <iostream>
#include "A.h"
#include "B.h"
int main(int argc, char* argv[])
{
A a(10);
B b(3.14);
a.Print();
a.SetB(&b);
b.Print();
b.SetA(&a);
return 0;
}
Here is the solution for templates: How to handle circular dependencies with templates
The clue to solving this problem is to declare both classes before providing the definitions (implementations). It’s not possible to split the declaration and definition into separate files, but you can structure them as if they were in separate files.
The simple example presented on Wikipedia worked for me.
(you can read the complete description at http://en.wikipedia.org/wiki/Circular_dependency#Example_of_circular_dependencies_in_C.2B.2B )
File '''a.h''':
#ifndef A_H
#define A_H
class B; //forward declaration
class A {
public:
B* b;
};
#endif //A_H
File '''b.h''':
#ifndef B_H
#define B_H
class A; //forward declaration
class B {
public:
A* a;
};
#endif //B_H
File '''main.cpp''':
#include "a.h"
#include "b.h"
int main() {
A a;
B b;
a.b = &b;
b.a = &a;
}
Unfortunately, all the previous answers are missing some details. The correct solution is a little bit cumbersome, but this is the only way to do it properly. And it scales easily, handles more complex dependencies as well.
Here's how you can do this, exactly retaining all the details, and usability:
the solution is exactly the same as originally intended
inline functions still inline
users of A and B can include A.h and B.h in any order
Create two files, A_def.h, B_def.h. These will contain only A's and B's definition:
// A_def.h
#ifndef A_DEF_H
#define A_DEF_H
class B;
class A
{
int _val;
B *_b;
public:
A(int val);
void SetB(B *b);
void Print();
};
#endif
// B_def.h
#ifndef B_DEF_H
#define B_DEF_H
class A;
class B
{
double _val;
A* _a;
public:
B(double val);
void SetA(A *a);
void Print();
};
#endif
And then, A.h and B.h will contain this:
// A.h
#ifndef A_H
#define A_H
#include "A_def.h"
#include "B_def.h"
inline A::A(int val) :_val(val)
{
}
inline void A::SetB(B *b)
{
_b = b;
_b->Print();
}
inline void A::Print()
{
cout<<"Type:A val="<<_val<<endl;
}
#endif
// B.h
#ifndef B_H
#define B_H
#include "A_def.h"
#include "B_def.h"
inline B::B(double val) :_val(val)
{
}
inline void B::SetA(A *a)
{
_a = a;
_a->Print();
}
inline void B::Print()
{
cout<<"Type:B val="<<_val<<endl;
}
#endif
Note that A_def.h and B_def.h are "private" headers, users of A and B should not use them. The public header is A.h and B.h.
Unfortunately I can't comment the answer from geza.
He is not just saying "put forward declarations into a separate header". He says that you have to spilt class definition headers and inline function definitions into different header files to allow "defered dependencies".
But his illustration is not really good. Because both classes (A and B) only need an incomplete type of each other (pointer fields / parameters).
To understand it better imagine that class A has a field of type B not B*. In addition class A and B want to define an inline function with parameters of the other type:
This simple code would not work:
// A.h
#pragme once
#include "B.h"
class A{
B b;
inline void Do(B b);
}
inline void A::Do(B b){
//do something with B
}
// B.h
#pragme once
class A;
class B{
A* b;
inline void Do(A a);
}
#include "A.h"
inline void B::Do(A a){
//do something with A
}
//main.cpp
#include "A.h"
#include "B.h"
It would result in the following code:
//main.cpp
//#include "A.h"
class A;
class B{
A* b;
inline void Do(A a);
}
inline void B::Do(A a){
//do something with A
}
class A{
B b;
inline void Do(B b);
}
inline void A::Do(B b){
//do something with B
}
//#include "B.h"
This code does not compile because B::Do needs a complete type of A which is defined later.
To make sure that it compiles the source code should look like this:
//main.cpp
class A;
class B{
A* b;
inline void Do(A a);
}
class A{
B b;
inline void Do(B b);
}
inline void B::Do(A a){
//do something with A
}
inline void A::Do(B b){
//do something with B
}
This is exactly possible with these two header files for each class wich needs to define inline functions.
The only issue is that the circular classes can't just include the "public header".
To solve this issue I would like to suggest a preprocessor extension: #pragma process_pending_includes
This directive should defer the processing of the current file and complete all pending includes.
First we need a few definitions.
Definitions
Declaration
extern int n;
int f();
template<typename T> int g(T);
struct A;
template<typename T> struct B;
Definition
int n;
int f() { return 42; }
template<typename T> int g(T) { return 42; }
struct A { int f(); };
template<typename T> struct B { int g(T*); };
The difference is that repeating a definition causes a One Definition Rule (ODR) violation. The compiler will give an error along the lines of "error: redefinition of '...'".
Note that a "forward declaration" is just a declaration. Declarations can be repeated since they don't define anything and therefore cause no ODR.
Note that default arguments may only be given once, possibly during the declaration, but only for one of the declarations if there are multiple. Therefore one could argue that that is a definition because it may not be repeated (and in a sense it is: it defines the default arguments). However, since it doesn't define the function or template, lets call those a declaration anyway. Default arguments will be ignored below.
Function definitions
(Member) function definitions generate code. Having multiple of those (in different Translation Units (TU's), otherwise you'd get an ODR violation already during compile time) normally leads to a linker error; except when the linker resolves the collision which it does for inline functions and templated functions. Both might or might not be inlined; if they are not 100% of the time inlined then a normal function (instantiation) needs to exist; that might cause the collision that I am talking about.
Non-inline, non-template (member) functions need to exist only in a single TU and should therefore be defined in a single .cpp.
However, inline- and/or template (member) functions are defined in headers, which might be included by multiple TU's, and therefore need special treatment by the linker. They too are considered to generate code however.
Class definitions
Class definitions might or might not generate code. If they do, then that is for functions that the linker will resolve any collisions of.
Of course, any member function that is defined inside the class is per definition "inline". If it is a problem that such a function is defined during the declaration of the class, it can simply be moved outside the class declaration.
Instead of,
struct A {
int f() const { return 42; }
};
do
struct A {
inline int f() const;
}; // struct declaration ends here.
int A::f() const { return 42; }
Therefore we are mostly interested in code generation (function instantiations) that both, can not be moved outside the class declaration and requires some other definition in order to be instantiated.
It turns out that this usually involves smart pointers and default destructors. Assume that struct B can not be defined, only declared, and struct A looks as follows:
struct B;
struct A { std::unique_ptr<B> ptr; };
then an instantiation of A while the definition of B is not visible (some compilers might not mind if B is defined later in the same TU) will cause an error because both, the default constructor as well as the destructor of A, cause the destructor of unique_ptr<B> to be generated, which needs the definition of B [e.g. error: invalid application of ‘sizeof’ to incomplete type ‘B’]. There is still a way around this though: do not use generated default constructor/destructor.
For example,
struct B;
struct A {
A();
~A();
std::unique_ptr<B> ptr;
};
will compile and just have two undefined symbols for A::A() and A::~A() which you can still compile inline outside of the definition of A as before (provided you define B before you do so).
Three parts, three files?
As such we can distinguish three part of a struct/class definition that we could each put in a different file.
The (forward) declaration:
A.fwd.h
The class definition:
A.h
The inline and template member function definitions:
A.inl.h
And then there is of course A.cpp with the non-inline and non-template member function definitions; but those are not relevant for circular header dependencies.
Ignoring default arguments, declarations won't require any other declaration or definition.
Class definitions might require certain other classes to be declared, yet others to be defined.
Inline/template member functions might require additional definitions.
We can therefore create the following example that show all possibilities:
struct C;
struct B
{
B();
~B();
std::unique_ptr<C> ptr; // Need declaration of C.
};
struct A
{
B b; // Needs definition of B.
C f(); // Needs declaration of C.
};
inline A g() // Needs definition of A.
{
return {};
}
struct D
{
A a = g(); // Needs definition of A.
C c(); // Needs declaration of C.
};
where B::B(), B::~B(), C A::f() and C D::c() are defined in some .cpp.
But, lets inline those as well; at that point we need to define C because all four need that (B::B and B::~B because of the unique_ptr, see above). And doing so in this TU then suddenly makes it unnecessary to put B::B() and B::~B() outside of the definition of B (at least with the compiler that I am using). Nevertheless, lets keep B as it is.
Then we get:
// C.fwd.h:
struct C;
// B.h:
struct B
{
inline B();
inline ~B();
std::unique_ptr<C> ptr;
};
// A.h:
struct A
{
B b;
inline C f();
};
// D.h:
inline A g()
{
return {};
}
struct D
{
A a = g();
inline C c();
};
// C.h:
struct C {};
// B.inl.h:
B::B() {}
B::~B() {}
// A.inl.h:
C A::f()
{
D d;
return d.c();
}
// D.inl.h:
C D::c()
{
return {};
}
In other words, the definition of A looks like this:
// A.fwd.h:
struct A;
// A.h:
#include "B.h" // Already includes C.fwd.h, but well...
#include "C.fwd.h" // We need C to be declared too.
struct A
{
B b;
inline C f();
};
// A.inl.h:
#include "A.h"
#include "C.h"
#include "D.inl.h"
C A::f()
{
D d;
return d.c();
}
Note that in theory we could make multiple .inl.h headers: one for each function, if otherwise it drags in more than required and that causes a problem.
Forbidden patterns
Note that all #include's are at the top of all files.
(In theory) .fwd.h headers do not include other headers. Therefore they can be included at will and never lead to a circular dependency.
.h definition headers might include a .inl.h header, but if that leads to a circular header dependency then that can always be avoided by moving the function that uses the inlined function from that .inl.h to the .inl.h of the current class; in the case of smart pointers that might require to also move the destructor and/or constructor to that .inl.h.
Hence, the only remaining problem is a circular inclusion of .h definition headers, ie A.h includes B.h and B.h includes A.h. In that case you must decouple the loop by replacing a class member with a pointer.
Finally, it is not possible to have a loop of pure .inl.h files. If that is necessary you probably should move them to a single file in which case the compiler might or might not be able to solve the problem; but clearly you can't get ALL functions inlined when they use eachother, so you might as well manually decide which can be non-inlined.
In some cases it is possible to define a method or a constructor of class B in the header file of class A to resolve circular dependencies involving definitions.
In this way you can avoid having to put definitions in .cc files, for example if you want to implement a header only library.
// file: a.h
#include "b.h"
struct A {
A(const B& b) : _b(b) { }
B get() { return _b; }
B _b;
};
// note that the get method of class B is defined in a.h
A B::get() {
return A(*this);
}
// file: b.h
class A;
struct B {
// here the get method is only declared
A get();
};
// file: main.cc
#include "a.h"
int main(...) {
B b;
A a = b.get();
}

Circular inclusion issue with extended class c++

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;
};