Avoid forward redeclaration. Is it a good practice? Is it necessary? - c++

I am used to do forward declarations of classes like this:
// file 1
#ifndef A_HPP
#define A_HPP
class A
{
...
};
#endif
// file 2
#ifndef B_HPP
#define B_HPP
#ifndef A_HPP
class A;
#endif
class B
{
};
#endif
As you can see in file 2, I try to safe the forward declaration of A. So, it should not be possible to redeclare A.
I have seen a lot of code where they don't put the guards around the forward declarations.
I wanted to know if what I am doing is really necessary or if it adds some kind of safety. Would any of these approaches benefit compilation times more than the other? Which one would you use? Why?

You are NOT adding any safety. Declarations in C++ can be repeated any times you want, as long as they are all coherent.
Furthermore, this is not a good practice. I've never seen someone doing like that. Think what would happen if you move A's definition from a.hpp: you should change all the scope guards around A's forward declaration in all files. Life is already complicated enough.

You dont need to use the marco guard as compiler will know how to process both file.
No need to out the follow 3 lines in file2.h
#ifndef A_HPP
class A;
#endif
use the following line is already good enough
#include "file1.h"
The concept of forward declaration
forward declaration is used to notify compiler there is a class ( or struct or whatever type you want ) named as "A" when reading the file. but compiler knows the declaration is not specific here, but may be in the other file.
At that time, compiler will know:
1) OK, there is a class named as "A", I will remember it.
2) I dont know its size and detail. But if coder use only the A* (pointer of A), it is OK and I dont need to know the detail of A.
Forward declaration is useful. Especially classes are interrelated.
But, if the type name of A is not in sync between both files. g++ will fail to compile.
Compilation time
Forward declaration is also good to use as it save the compilation time.
If the file does not change, g++ will not re-compile again.
While the file 2 use only the forward declaration, so no matter how you change the file 1 or class A, file 2 will not be compile again.

Related

Forward declaration / when best to include headers?

I'm pretty clear on when I can/can't use forward declaration but I'm still not sure about one thing.
Let's say I know that I have to include a header sooner or later to de-reference an object of class A.
I'm not clear on whether it's more efficient to do something like..
class A;
class B
{
A* a;
void DoSomethingWithA();
};
and then in the cpp have something like..
#include "A.hpp"
void B::DoSomethingWithA()
{
a->FunctionOfA();
}
Or might I as well just include A's header in B's header file in the first place?
If the former is more efficient then I'd appreciate it if someone clearly explained why as I suspect it has something to do with the compilation process which I could always do with learning more about.
Use forward declarations (as in your example) whenever possible. This reduces compile times, but more importantly minimizes header and library dependencies for code that doesn't need to know and doesn't care for implementation details. In general, no code other than the actual implementation should care about implementation details.
Here is Google's rationale on this: Header File Dependencies
When you use forward declaration, you explicitly say with it "class B doesn't need to know anything about internal implementation of class A, it only needs to know that class named A exists". If you can avoid including that header, then avoid it. - it's good practice to use forward declaration instead because you eliminate redundant dependencies by using it.
Also note, that when you change the header file, it causes all files that include it to be recompiled.
These questions will also help you:
What are the drawbacks of forward declaration?
What is the purpose of forward declaration?
Don't try to make your compilation efficient. There be dragons. Just include A.hpp in B.hpp.
The standard practice for C and C++ header files is to wrap all of the header file in an #ifndef to make sure it is compiled only once:
#ifndef _A_HPP_
#define _A_HPP_
// all your definitions
#endif
That way, if you #include "A.hpp" in B.hpp, you can have a program that includes both, and it won't break because it won't try to define anything twice.

Another C++ was not declared in this scope error

Several questions has been asked related to this error, but each one of them practically relates to the object or type in question not declared before usage. For example:
class A
{
public:
A_Object a_obj;
};
Getting the error A_Object was not declared in this scope means A_object is not declared anywhere within the file.
NOTE: This is my understanding of the error.
Now I have a file called Account.h as shown below:
#ifndef ACCOUNT_H_
#define ACCOUNT_H_
class Account
{
//fields and methods
};
#endif /* ACCOUNT_H_ */
I also have a second file called Address.h as shown below:
#ifndef ADDRESS_H_
#define ADDRESS_H_
#include "Account.h"
typedef Account account_type;//Error here
class Address
{
//Fields and methods
};
#endif /* ADDRESS_H_ */
When I try to compile this file I get the error Account was not declared in this scope.
Any Ideas why?
Does Account.h actually also include Address.h? Such a circular reference seems the most likely situation.
Do you have a matching #endif at the end of both include files?
First point, your understanding about A_object is incorrect, the error means that A_object was not declared prior to it's first use, not that it wasn't declared anywhere.
Second point, the code you posted is incorrect, because you are missing #endif from both files. But assuming that was the only missing code then you would not get the error you describe. Post the real code that has the error.
I've seen this error when Address.h includes Account.h, which includes OtherFile.h, which includes Address.h. Is it possible you have a circular dependency? It may be hard to find.
This might be a case where a more core understanding of how the c/c++ compiler works would be in order. Include blocks, forward declarations, includes etc. All of these concepts did not make sense to me until I understood the basics of how compiler works. While I realize that this is somewhat of an oversimplification of compiler theory / logic, bear with me.
One of the first steps that a c++ compiler performs is a pre-processing (pre-compiler) step where it takes all of the files that are required, and combines them into one big flat file. In "C" languages, these pre-compiler operations a denoted using the hash (#) symbol. All an "#include" is doing, is directing the pre-compiler to bring this file into the entire "flat-file". If you have a cyclic include, your pre-compiler will get into an infinite loop and blow up, or say something super generic and useful like "the symbol has already been defined".
Include blocks, forward declarations, and all of the neat things that you are taught in c++ books that say "just do it, trust me" generally are helping you to avoid these type of compiling problems.

Proper way to #include when there is a circular dependency?

I'm using #pragma once, not #include guards on all my h files. What do I do if a.h needs to #include b.h and b.h needs to #include a.h?
I'm getting all sorts if errors because by doing this, the pragma once takes effect and one of them is missing each other. How should I do this.
Thanks
You need to forward declare the definitions you need. So if A uses B as a parameter value, you need to forward declare B, and vice versa.
It could be that just forward declaring the class names:
class A;
class B;
solves your problems.
The accepted answer to this question provides some additional guidance.
One possibility is to refactor some portion of the files a.h and b.h into a third file say c.h, and include it from both a.h and b.h. This way, the latter two would no longer need to mutually include each other.
Another possibility is to merge the separate header files into one.
A third possibility is the situation when two classes legitimately need to refer to each other. In such cases you have to use pointers. Moreover, you can forward declare the class instead of including its header file. [Mentioned also by jdv] For example,
// file a.h
struct B;
struct A { B * b_ };
// file b.h
struct A;
struct B { A * a_; };
However, without knowing your particular situation it is difficult to provide specific suggestion.
It depends on what is needed from each other's header file. IF it's a class definition, but it only is using a pointer to the class, then instead of including the head file just put in a forward declaration like:
class MyClassA;
The solution for this issue is 'forward declaration'.
If you have a class or a function that needs to be used in 2 headers one of the headers needs to forward declare the used class or type.
Or you need to consider to restructure your headers.
This is a common beginner issue that circular dependencies are causing such issues. If you google on 'forward declaration' will find tons of results.
Since your question was too unspecific I can't give you an exact answer, sorry for this.
You can not use incomplete types, but you can just forward declare them. You just tell the compiler:"Don't get syntax errors, I know what i am doing". Which means that the linker will go and find complete types from libraries whatsoever.

forward declaration of class

In A.h I have the following class
class A
{
int a;
char name[100];
}
B.h has the following code
class A;
Class B
{
public:
int c;
float d;
getObjectDetails(A *);
};
I compiled it as g++ A.h B.h B.cpp -o out. But it gives compilation errors saying class A is incomplete. Could any one please help me understand?
Also, if I include header file A.h in B.h, everything goes fine. In that case, I need not declare Class A before Class B definition I think, I can directly create and use instance of class A. Could anyone clarify me on this point?
what happens in step "class A" declaration at compile time and run time?
You can only use forward declarations
with pointers and references (because
these are of a fixed size, independent
of the size of the object they refer
to). If you use a specific class by
value, the compiler needs its full
definition (in order to know its exact
size), thus forward declaration is not
enough.
You can only use forward declarations
for type identification, such as when
you use the declared type in a
function/method pointer parameter
prototype. If you are going to declare
a member variable (i.e. std::string
_name;) the compiler needs a little bit more than a forward declaration
can give it. For example, if someone
does a sizeof(Student) the compiler
has to have access to the entire
declaration to figure out the size.
Answer by Péter Török from this thread.
It should compile fine, if you
1) add a semi-colon at the end of class A declaration.
2) change "C" to "c" in class B declaration.
3) add a return type to getObjectDetails()
The problem is surely in B.cpp, because B.h is fine. If you are trying to do anything with the A* received by getObjectDetails() (such as calling a method on it), the compiler will not be able to understand it.
To fix it, try including A.h in B.cpp (B.h does not need it, indeed).
You probably don't have #include "A.h" in B.cpp, which is then using A in such a way that it requires A to be defined, not just declared. Absent the definition, just about the only thing you can do with the A* passed to getObjectDetails is store it in an A* or void* variable, or pass it on to some other code outside B.cpp.
You should #include A.h from B.h. What you've done instead is called a forward declaration, and is only recommended when A.h either contains an enormous amount of code, or includes other files that do. Then, the "class A;" thing can be a quick way to let your compiler know that A is a class, and hence accept pointers and reference to A objects, without parsing all the extra code from A.h. Your A.h is not long enough to justify such a hack. It is much better to directly use the authoratative source of information about A, which is A.h, instead of spreading information about A (which may one day cease to be true) throughout B. I actively dislike this forward declaration hack, and recommend creating a dedicated forward declaration header that contains "class A;" and any other classes A.h grows to contain, so that uses like B can include that if they don't need the full declarations. This is done by the Standard Library in , which forward declares useful classes, variables and constants for the heavier-weight .
Then, your B.cpp should #include B.h. Your command line should simply be:
g++ B.cpp -o out
(no need to mention A.h or B.h as they will be included (indirectly and directly respectively) from B.cpp.
This code
class A;
class B
{
public:
int c;
float d;
void getObjectDetails(A *);
};
compiles fine for me using VC9 (VS 2008) and I believe this to be correct.
If your code does not compile, it differs from the above in a significant detail. The only way for you to find that (there's no way for us to find it) is to take (a copy of) your original code, and start removing things step by step until the error goes away.
Either you then understand what the problem is or you end up with <20 lines of self-contained example code which reproduce the error - a perfect repro to come back here and ask about.

C++ Headers - Best practice when including

C++ headers
If I have A.cpp and A.h as well as b.h, c.h, d.h
Should I do:
in A.h:
#include "b.h"
#include "c.h"
#include "d.h"
in A.cpp:
#include "A.h"
or
in A.cpp:
#include "A.h"
#include "b.h"
#include "c.h"
#include "d.h"
Are there performance issues? Obvious benefits? Is something bad about this?
You should only include what is necessary to compile; adding unnecessary includes will hurt your compilation times, especially in large projects.
Each header file should be able to compile cleanly on its own -- that is, if you have a source file that includes only that header, it should compile without errors. The header file should include no more than is necessary for that.
Try to use forward declarations as much as possible. If you're using a class, but the header file only deals with pointers/references to objects of that class, then there's no need to include the definition of the class -- just use a forward declaration:
class SomeClass;
// Can now use pointers/references to SomeClass
// without needing the full definition
The key practice here is having around each foo.h file a guard such as:
#ifndef _FOO_H
#define _FOO_H
...rest of the .h file...
#endif
This prevents multiple-inclusions, with loops and all such attendant horrors. Once you do ensure every include file is thus guarded, the specifics are less important.
I like one guiding principle Adam expresses: make sure that, if a source file just includes a.h, it won't inevitably get errors due to a.h assuming other files have been included before it -- e.g. if a.h requires b.h to be included before, it can and should just include b.h itself (the guards will make that a noop if b.h was already included previously)
Vice versa, a source file should include the headers from which it is requiring something (macros, declarations, etc), not assume that other headers just come in magically because it has included some.
If you're using classes by value, alas, you need all the gory details of the class in some .h you include. But for some uses via references or pointers, just a bare class sic; will suffice. E.g., all other things being equal, if class a can get away with a pointer to an instance of class b (i.e. a member class b *my_bp; rather than a member class b *my_b;) the coupling between the include files can be made weaker (reducing much recompilation) -- e.g. b.h could have little more than class b; while all the gory details are in b_impl.h which is included only by the headers that really need it...
What Adam Rosenfield told you is spot on. An example of when you can use a forward declaration is:
#ifndef A_H_
#define A_H_
#include "D.h"
class B; //forward declaration
class C; //forward declaration
class A
{
B *m_pb; //you can forward declare this one bacause it's a pointer and the compilier doesn't need to know the size of object B at this point in the code. include B.h in the cpp file.
C &m_rc; //you can also forware declare this one for the same reason, except it's a reference.
D m_d; //you cannot forward declare this one because the complier need to calc the size of object D.
};
#endif
Answer: Let A.h include b.h, c.h and d.h only if it's needed to make the build succeed. The rule of thumb is: only include as much code in a header file as necessary. Anything which is not immediately needed in A.h should be included by A.cpp.
Reasoning: The less code is included into header files, the less likely you will need to recompile the code which uses the header file after doing some change somewhere. If there are lots of #include references between different header files, changing any of them will require rebuilding all other files which include the changed header file - recursivel. So if you decide to touch some toplevel header file, this might rebuild huge parts of your code.
By using forward declarations wherever possible in your header files, you reduce the coupling of the source files and thus make the build faster. Such forward declarations can be used in many more situations than you might think. As a rule of thumb, you only need the header file t.h (which defines a type T) if you
Declare a member variable of type T (note, this does not include declaring a pointer-to-T).
Write some inline functions which access members of an object of type T.
You do not need to include the declaration of T if your header file just
Declares constructors/functions which take references or pointers to a T object.
Declares functions which return a T object by pointer, reference or value.
Declares member variables which are references or pointers to a T object.
Consider this class declaration; which of the include files for A, B and C do you really need to include?:
class MyClass
{
public:
MyClass( const A &a );
void set( const B &b );
void set( const B *b );
B getB();
C getC();
private:
B *m_b;
C m_c;
};
You just need the include file for the type C, because of the member variable m_c. You can often remove this requirement as well by not declaring your member variables directly but using an opaque pointer to hide all the member variables in a private structure, so that they don't show up in the header file anymore.
Prefer not including headers in other headers - it slows down compilation and leas to circular reference
There would be no performance issues, it's all done at compile time, and your headers should be set up so they can't be included more than once.
I don't know if there's a standard way to do it, but I prefer to include all the headers I need in source files, and include them in the headers if something in the header itself needs it (for example, a typedef from a different header)