Forward Declaration vs Include

35,484

Solution 1

Case 1 will produce an "incomplete type" error when you compile B.cpp. Because class B contains a class A object, the definition (and in particular the size) of class A is required to be complete before the definition of class B.

Alternatively, you could choose to make some_variable a pointer or reference to class A, and in that case your forward declaration would be sufficient in B.h. You'd still need a full definition of A in B.cpp (assuming you made actual use of the A member functions/data).

Solution 2

Forward declaration is not a substitute for Header file inclusion.

As the name itself implies, forward declaration is just a Declaration and not a definition.

So, you will declare saying the compiler that it is a class and I just declaring it here and will provide you the definition when am gonna use it. So, normally you forward declare in the Header file and #include in the .cpp file where you will use the members of the forward declared class.

By doing so, what you make is, wherever you are including the header file there will just be a declaration for the class instead of the entire contents #included...

But having said that, when the compiler requires the definition of the class, it should be #included..

So, in your case A obj; requires the definition of class A and hence you should #include..

I myself asked a similar question here and another similar question which has also a nice answer...

Hope it helps..

Solution 3

You need to use forward declarations in cases where you have classes that refer to each other.

//A.h

class B;

class A {
    B* someVar;
}

//B.h
#include <A.h>

class B {
    A* someVar;
}

But there's no benefit for doing it in the case you laid out.

Solution 4

Think like a compiler. In order to create an A inside of B, the compiler has to know how to build an A, and the only way to do that is to have the complete definition. The forward declaration tells the compiler that class A exists without describing what it looks like; this is adequate for defining a pointer or a reference. When it comes time to use that pointer or reference, the complete class definition will be required.

Solution 5

If you meant to portray some_variable as a pointer then the frequently recommended practice is to use forward declarations whenever possible to avoid the overhead of includes and longer compile times.

I'm all for best practices but I really like using IDEs that have nice code navigation features and forwards cause a problem there, at least with Netbeans. Whenever I try to navigate to a type declaration, I always end up at the forward and not the .h file containing the actual declaration. I'm willing to accept some extra compile time for the ease of navigation. Maybe this is just a problem with Netbeans :)

.. oh yeah.. If you look at the related questions to the right of your question, you will find lots of additional information of forward declarations.

Share:
35,484

Related videos on Youtube

Sii
Author by

Sii

Updated on July 09, 2022

Comments

  • Sii
    Sii almost 2 years

    Consider the following two scenarios (Edited just to complete the whole question and make it clearer)

    Case 1: (doesnt compile as rightly mentioned below)

    //B.h
    #ifndef B_H
    #define B_H
    #include "B.h"
    
    class A;
    
    class B { 
            A obj;
            public:
            void printA_thruB();
    
             };  
    #endif
    
    //B.cpp
    #include "B.h"
    #include <iostream>
    
    void B::printA_thruB(){
            obj.printA();
            }   
    
    
    //A.h;
    #ifndef A_H
    #define A_H
    
    #include "A.h"
    
    class A { 
            int a;
            public:
            A();
            void printA();
    
             };  
    #endif   
    
    //A.cpp                           
    #include "A.h"                    
    #include <iostream>               
    
    A::A(){                           
            a=10;                     
            }                         
    
    void A::printA()                  
    {                                 
    std::cout<<"A:"<<a<<std::endl;    
    }  
    
    
    //main.cpp
     #include "B.h"
      #include<iostream>
     using namespace std;
    
     int main()
     {
     B obj;
     obj.printA_thruB();
     }
    

    Case 2: (the only modifications...works without compiliation error)

    //B.h
    
    #include "A.h" //Add this line
    //class A;     //comment out this line
    

    Let us assume both the A.cpp and B.cpp are complied together. Do the above two scenarios make any differences? Is there a reason to prefer one method over the other?

    Edit: So how do I make scenario 1 work.

    • Dennis Zickefoose
      Dennis Zickefoose over 13 years
      So you've compiled A.cpp and B.cpp together, but what have you done with A.h and B.h?
    • Sii
      Sii over 13 years
      @Dennis Made the question clearer for you
  • Hitesh
    Hitesh over 13 years
    A clarification. Case 1 will only produce a compile error if you attempt to call any methods on A. In this case it should give an error since you will be implicitly calling the constructor. But in a different scenario if one of B's methods simply received a pointer to an A object, which it then passed in to some other method/function that was outside of B's responsibility, then the compiler would be fine not knowing the definition of A.
  • Sii
    Sii over 13 years
    Thanks for the info. what if B is access some variable of A in my case.
  • Sii
    Sii over 13 years
    you are right Drew I do get a compile Error. So how can I over come that? I thought forward declarations can be used instead of header inclusion.
  • Sii
    Sii over 13 years
    This is what i was trying to avoid..the unwanted header inclusion.
  • Hitesh
    Hitesh over 13 years
    In your case you really want to use the explicit include of A.h inside of B.h. There are only two instances that I've seen forward references used: the first I mentioned above with regard to circular references and the second was a case where a vendor provided header files that had some classes defined only as forward references. They had scrubbed their header files to protect their proprietary information. The net result is that it was a nightmare to work with their API -- I don't recommend it.
  • Sii
    Sii over 13 years
    So if I include the header "A.h" in B.cpp file and just forward declare class A in B.h isnt it supposed to work?
  • Sii
    Sii over 13 years
    I was trying to do something similar ..remove the header from the interface (.h) and forward declare the class which I am trying to use.
  • Mark Ransom
    Mark Ransom over 13 years
    @MrProg, no it won't work - B.h defines how to create a B, but you can't create a B without knowing how to create an A because B contains an A. You can store a pointer or reference to an A without knowing how to create an A, which is why the forward reference can be useful, just not in your case.
  • Sii
    Sii over 13 years
    if I change the A obj to A *obj and do as I mentioned above an also make the int a in class A as public, I am able to compile..but I do get the segmentation fault. So I gues my understanding of forward declaration need to be rethinked.
  • Sii
    Sii over 13 years
    While including the headers we do the same thing..it is just declaration..definition goes in the .cpp sources file. So if I change my A obj to A *obj which is a pointer it is supposed to work right.( but doesnt)
  • Sii
    Sii over 13 years
    Thanks for the help..I have confused myself enough for a day me thinks.
  • Drew Hall
    Drew Hall over 13 years
    @Hitesh: No. Case 1 will always produce a compile error because the compiler doesn't know sizeof(A), and thus it can't know how to lay out a B object.
  • Drew Hall
    Drew Hall over 13 years
    @MrProg: You either need to fully define A (by including A.h) before you define class B, or you need to change to containing a pointer or reference to A within B. In this case the easy/obvious solution is to include A.h in B.h. Why do you seem to be reluctant to do so?
  • Sii
    Sii over 13 years
    @Drew No.I was trying to get my head around forward declaration and was assuming it made the class accessible without including the headers...something similar to extern.
  • Drew Hall
    Drew Hall over 13 years
    @MrProg: Almost right. It tells the compiler that a class by that name exists--which is enough to allow declaration of a reference or a pointer to that type (but nothing else).
  • Hitesh
    Hitesh over 13 years
    @Drew, agree that case 1 as defined will produce compile error. Was trying to explain that in other scenarios, forward declarations without matching definitions might not result in compile errors to help MrProg learn more about them.