About friend classes
-
Hi,
I have two classes A, B.
B is a friend of class A.
I use VS2015.So I wrote the following headers and cpp:
A.h
#ifndef A_H #define A_H class B; class A { private: ... public: ... friend class B; } #endif
B.h
#ifndef B_H #define B_H class A; class B { private: A* a; public: void B::writeHeader(); ... } #endif
B.cpp
void B::writeHeader() { a->... = ... }
The issue is in function writeHeader().
As I start to type a->, VS 2015 doesn't display the list of private mebers of the class A. I does when I replace class A; with #include "A;h".
Could you explain please ?
Thanks -
@mulfycrowh said:
As I start to type a->, VS 2015 doesn't display the list of private mebers of the class A. I does when I replace class A; with #include "A;h".
Could you explain please ?That's pretty normal. Basically, the
class A;
is forward declaration that the tells the compiler (and VS) that some class "A" exists somewhere, but doesn't tell it anything about what A actually is.Used in this way, there's very little the compiler can do with A, because it doesn't know what it is. The one real exception being, that you can declare a pointer to A as part of B (member variables, etc).
To actually use A in any other way (including dereferencing pointers to A), requires a the compiler (and VS) to know what A actually is, and usual (including your case), that means including
A.h
.For example:
// B.h class A; class B { .... A *a; } // B.cpp #include "A.h" B::B() { a->... // Okay, since we've included "A.h" }
So then, if
A.h
is available, why not simply include it inB.h
and not bother with theclass A;
forward declaration? The answer is mostly (IMO) compile-time performance. If, for example, we had some class C that used B, but not A, then as shown above,C.h
can includeB.h
without the compiler having to parse (unnecessarily) all ofA.h
too. In this super-simple example, the difference in negligible, but for large scale projects / libraries such as Qt, the difference can be massive (both in time and memory usages during compilation).Some optional further reading:
- http://stackoverflow.com/questions/9906402/should-one-use-forward-declarations-instead-of-includes-wherever-possible (they say "yes")
- https://google.github.io/styleguide/cppguide.html#Forward_Declarations (they say "no")
Cheers.
-
@mulfycrowh said:
As I start to type a->, VS 2015 doesn't display the list of private mebers of the class A. I does when I replace class A; with #include "A;h".
Could you explain please ?That's pretty normal. Basically, the
class A;
is forward declaration that the tells the compiler (and VS) that some class "A" exists somewhere, but doesn't tell it anything about what A actually is.Used in this way, there's very little the compiler can do with A, because it doesn't know what it is. The one real exception being, that you can declare a pointer to A as part of B (member variables, etc).
To actually use A in any other way (including dereferencing pointers to A), requires a the compiler (and VS) to know what A actually is, and usual (including your case), that means including
A.h
.For example:
// B.h class A; class B { .... A *a; } // B.cpp #include "A.h" B::B() { a->... // Okay, since we've included "A.h" }
So then, if
A.h
is available, why not simply include it inB.h
and not bother with theclass A;
forward declaration? The answer is mostly (IMO) compile-time performance. If, for example, we had some class C that used B, but not A, then as shown above,C.h
can includeB.h
without the compiler having to parse (unnecessarily) all ofA.h
too. In this super-simple example, the difference in negligible, but for large scale projects / libraries such as Qt, the difference can be massive (both in time and memory usages during compilation).Some optional further reading:
- http://stackoverflow.com/questions/9906402/should-one-use-forward-declarations-instead-of-includes-wherever-possible (they say "yes")
- https://google.github.io/styleguide/cppguide.html#Forward_Declarations (they say "no")
Cheers.
@Paul-Colby said:
So then, if A.h is available, why not simply include it in B.h and not bother with the class A; forward declaration? The answer is mostly (IMO) compile-time performance.
There are two better reasons to do it, beside the compile time performance.
- Breaking cyclic dependency (A uses B, and B uses A)
- Hiding private/implementation information.
-
Many thanks to everybody for These explanations !