0

My experience in c++ is very limited, so I excuse if my question is dumb or elementary. Here goes:

When doing larger project in a language like c++, and you possibly have a very big line of inheritance, is it normal practice to include every single derived class in the.. main file, let's say. Is there some way to circumvent this, or am I missing something banal?

Thank you.

  • Open your C++ book to the part that explains how to use forward declarations, and what their limitations are, for more information. – Sam Varshavchik Feb 25 '20 at 18:56
  • 2
    If `A` is a base of class of `B` is a base class of `C`, and each of these have their own header file `a.h`, `b.h`, `c.h`, then `c.h` will (hopefully and generally) include `b.h` which will include `a.h`. There's no need to `#include` `a.h` and `b.h` if you only need functionality of `c.h`. – JohnFilleau Feb 25 '20 at 18:57
  • Every header a file needs should be included. Do not count on headers including other headers. At any time a header you need and didn't include could be removed from a header that you did include and cause the build to to break . – user4581301 Feb 25 '20 at 18:57
  • Rather lengthy, but here's a great [example](https://stackoverflow.com/questions/11747954/c-inheritance-in-separate-files-using-include-and-inclusion-guards) – Kai Feb 25 '20 at 18:57
  • @user4581301 I agree with this if you're using instances of both a derived class and its base class, so you need the interface for both in your current `.cpp` file. If you only need the derived interface though, then no need to include both. – JohnFilleau Feb 25 '20 at 19:00
  • @John Thanks for the answer. If class B for example had 5 sub/derived classes, how would one go about getting the functionality from each of these without explicitly including them. – Jens Dissing Poulsen Feb 25 '20 at 19:00
  • 1
    ***If class B for example had 5 subclasses, how would one go about getting the functionality from each of these without explicitly including them*** You would need to include them if you want to use them in all in the same translation unit. – drescherjm Feb 25 '20 at 19:03
  • 2
    @Jens what do you mean by subclass? I always get direction of that fuzzy in my head. base and derived are the more C++ terms. If your current `.cpp` file directly uses objects of just class `B`, then only include `b.h`. If your current `.cpp` file directly uses objects of class `B`, `C`, `J`, and `Q`, then explicitly include `b.h`, `c.h`, `j.h`, and `q.h`. Don't rely on any of these to continue to inherit from any others (and therefore include each other) in the future. – JohnFilleau Feb 25 '20 at 19:03
  • Thanks a lot, you've been most helpful. – Jens Dissing Poulsen Feb 25 '20 at 19:05
  • What is the use of these subclasses? Perhaps a class factory would help? – drescherjm Feb 25 '20 at 19:06
  • 1
    @John That last comment of yours better explains the point I was trying to make. If you use X.h, include X.h. If you don't, leave it out. If Y.h needs X.h and doesn't include X.h, fix Y.h. – user4581301 Feb 25 '20 at 19:07
  • 1
    @Jens Are you certain you need five separate headers? If they are tightly related, they could all be in one header. A "God" header that collects common headers may also be suitable in some circumstances . – user4581301 Feb 25 '20 at 19:11
  • A very simple example would be to have an Animal base class and then derived classes for multiple species, where each of these have different functions. – Jens Dissing Poulsen Feb 25 '20 at 19:23
  • 1
    Clarification: By *each of these have different functions* do you mean different implementations of the same virtual functions or do you literally mean different functions? If the latter, you're headed in a direction that will likely bring you much difficulty. [The Liskov Substitution Principle](https://stackoverflow.com/questions/56860/what-is-an-example-of-the-liskov-substitution-principle) can help you correct things before they get out of hand. – user4581301 Feb 25 '20 at 19:34
  • @user4581301 Thanks to you as well, you have been a great help! – Jens Dissing Poulsen Feb 25 '20 at 20:00

1 Answers1

0

For a C++ program to use a C++ class, it requires the declaration. If the class inherits from base classes, then those declarations are required to process that class declaration. This applies recursively: the entire inheritance tree of the class is required.

If the inheritance graph is so deep and broad (perhaps due to multiple inheritance) that the project decides it is unacceptable, then it has to be restructured. Classes might be able to use aggregation instead of inheritance. So that is to say, instead of:

#include <widget.h>

class foo : public widget { ... };

it may be possible to have;

class widget; // "forward" declaration only; no #include needed
class foo { widget *pwidget; ...}

Now, only the file which implements foo needs the full declaration of widget; the clients of foo which are including "foo.h" don't need it.

But now foo is not a-kind-of widget any longer, which has implications on the code organization. foo still has the widget parts by way of creating an object and holding it. If widget conforms to some abstract interface for widgets, foo may be able to implement that, and delegate to the contained widget.

Another tool in minimizing dependencies is dependency inversion.

Kaz
  • 55,781
  • 9
  • 100
  • 149
  • More readiing on one of Kaz's points: [Composition Over Inheritance](https://en.wikipedia.org/wiki/Composition_over_inheritance) – user4581301 Feb 25 '20 at 19:09