简体   繁体   中英

Include in header file vs. forward-declare and include in .cpp

I have a class B, and I want to call members form class A. So:

1.

//A.h    
class B; 
class A 
{ 
private:
    B* m_p; 
}; 

//a.cpp
#include "B.h"

2.

// A.h
#include "B.h"

class A 
{ 
private: 
    B * impl_; 
}; 

which way is better and is this two similar when a small project with not too much dependence involves?

Your first way of doing it means that in ah , the existence of class B is known, but not its definition . This limits what you can do with B inside ah . For example, you can have variables of type B * , but not variables of type B (because for a declaration of a variable of type B the compiler must be able to see the full definition of B ). Also, if you have variables of type B * , you can't dereference the pointer (because for that, too, the definition of B must be known).

Therefore, your second choice – which doesn't have these problems – is preferred, and this is what most people use most of the time.

It's only special cases in which the first method may be useful. For example:

  • If the .h files include each other (but then you may get a number of further problems, also regarding include-guards; this is generally difficult and to be avoided);
  • If bh is extremely large and complex, so you'd like to avoid including it wherever possible because it slows down the compilation process.

Your first method is a forward declaration. Your second actually includes the class B.

When to use one over the other?

Use the first one when:

  • In the definition of A, you only have a pointer to B, ie not a member of B.
  • You never call any function of B from the definition of A. (ie all calls to member functions of B happen in the .cpp file where you actually implement A's member functions.)
  • You expect the interface or size of class B to change frequently, but not the interface of A. This way, if B changes, only the contents of a.cpp get recompiled, but ah (and other files that include ah) need not change.

Use the second one when:

  • You need to know the size of B. The compiler calculates a class's size using its class definition and the sizes of all its members. For example, if class A has a member that is of type B, then to calculate the size of A, the compiler needs to know the size of B; to know the size of B, you need to include bh
    • You need to call functions of class B. In order to know whether you're calling functions that actually exist, the compiler needs to know class B's interface, ie you need to include bh

Answer: 1 .
Take a look at http://www.umich.edu/~eecs381/handouts/handouts.html

C Header File Guidelines

C++ Header File Guidelines (by David Kieras, EECS Dept., University of Michigan) says:

Guideline #10. If an incomplete declaration of a type X will do, use it instead of #including its header Xh . If another struct or class type X appears only as a pointer or reference type in the contents of a header file, then you should not #include Xh, but just place an incomplete declaration of X (also called a "forward" declaration) near the beginning of the header file, as in: class X; See the handout Incomplete Declarations for more discussion of this powerful and valuable technique. Note that the Standard library includes a header of incomplete declarations that often suffices for the <iostream> library, named <iosfwd> . #include <iosfwd> whenever possible, because the <iostream> header file is extremely large (giant templates!).

只需在类A的标题中声明该类。

class B;

The second is better. It makes the B class a module that you include using the .h file. Consider the case where you subclass B in the future and you update A to use C . In the second case, you only replace the header #include and A 's make-up. In the first case, you have to change the forward declaration. Also, in the second case, you define more than just the symbol B .

And as in the comments, you should use #include "Bh" if the header file is in the same directory as the rest of the code.

Well what you're doing is called forward decleration, the reason you would want that is if you had something like class A that uses class B and ALSO class B that uses class A.

In a case where there is only one relation you can certainly use your second choice. If you need the double usage then at least one of your classes declerations would have to use forward decleration

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM