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



  • Include A.h in B.cpp. Otherwise, the IDE doesn't know what A is.



  • @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 in B.h and not bother with the class 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 include B.h without the compiler having to parse (unnecessarily) all of A.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:

    Cheers.


  • Qt Champions 2016

    @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.

    1. Breaking cyclic dependency (A uses B, and B uses A)
    2. Hiding private/implementation information.


  • Many thanks to everybody for These explanations !


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.