0

Is it not possible to include the baseclass header and have it include all of its subclasses through it?

I seem to have come to an circular dependency with my base class and its subclasses.

From the program entry, I need to initialize one of the subclasses based on user input. I thought I could include the header of the base class which includes the headers of the subclasses:

main.cpp

#include "baseclass.h"

int main()
{
    ...
}

baseclass.h

#include "sub1.h"

class Base
{
    public:
        int name;
};

sub1.h

#include "baseclass.h"

class Base; // forward declaration

class Sub : public Base
{
    public:
        int age;
};

So the dependency is:

main -> baseclass -> sub1 -> baseclass -> sub1 -> etc...

If I keep the forward declaration in, g++ -std=c++11 -o prog *.cpp throws:

error: invalid use of incomplete type 'class Base'

Removing:

error: expected class-name before '{' token {

Not sure how to resolve this without putting a middle "factory" that includes all the subclass headers which each include the baseclass header.

pstatix
  • 3,611
  • 4
  • 18
  • 40
  • @Zeta Header guards are in place – pstatix Aug 01 '18 at 07:51
  • 6
    Why do you include "sub1.h" into "baseclass.h"? – geza Aug 01 '18 at 07:51
  • @geza I was trying to only include the "baseclass.h" into `main.cpp` so that in `main()` I could call `Sub1 S;` without having to include the headers of all the subclasses. If that is not the correct way to accomplish what I want to do, then what perhaps do you recommend? – pstatix Aug 01 '18 at 07:54
  • Why do you forward declare `Base` and also include? You can't inherit from a forward declaration. – Robert Andrzejuk Aug 01 '18 at 07:57
  • @RobertAndrzejuk There is probably a conglomerate of "attempts" wrapped up in that post as I tried (aimlessly from SO searching) to resolve the dependency to achieve my desired goal which was a single include that allowed access to all my subclasses which I thought I could do through including the baseclass. – pstatix Aug 01 '18 at 07:58

3 Answers3

3

Remove the #include "sub1.h" from baseclass.h, and create a separate header file, which includes all the derived classes you need, and include this header file into main.cpp.

Note: this line class Base; // forward declaration is not needed.

geza
  • 28,403
  • 6
  • 61
  • 135
  • Ah, so this is the way to go. Is this standard C++ practice? I come from a Python background where I don't need to do this at all. – pstatix Aug 01 '18 at 07:56
  • @pstatix: That's one way. The other is not using separate "sub1.h" files, but putting base+all derived classes into one header file. But I'd recommend this approach only if the resulting header file is not too big. – geza Aug 01 '18 at 07:59
  • @pstatix: Note, that it seems weird in the first place, if "baseclass.h" defined all the derived classes. It's name is `baseclass`, so it should only give the definition of `Base`. And then you have a convenience "all_derived.h", which could give all the definitions of derived classes. – geza Aug 01 '18 at 08:01
  • I was trying to avoid having a header that simple contained 6-7 `#include sub_n.h` calls, thought it seemed like a bandaid to the bigger problem. Now it appears that having the "master" inclusion file is the way to resolve this. – pstatix Aug 01 '18 at 08:02
  • 1
    @pstatix: you can have it: you have to put `#include "sub_n.h"` at the end of `baseclass.h` (not at the beginning). But it's a very ugly solution, I don't recommend it, it could generate problems later. – geza Aug 01 '18 at 08:05
  • @pstatix You should learn how preprocessor works. Note that `#include` is not equivalent of python's `import`. – user7860670 Aug 01 '18 at 08:10
0

Remove #include "sub1.h" from base.h (also the class Base forward declaration). Where you wan't to use sub include sub1.h, in this case in the main. If you are actually building a bunch of sub type child classes then in all likelihood you will implement something to create them correctly anyway. That something would probably be a factory. It will look something like this:

// ClassFactory.h
#include "sub1.h"
#include "sub2.h"
...
#include "subN.h"

std::unique_ptr<Base> createClass(std::string name) {

    if (name == "sub1")
        return std::unique_ptr<Base>(new sub1());
    if (name == "sub2")
        return std::unique_ptr<Base>(new sub1());
    ...
    return nullptr;
}

And your main will include and use this file:

#include "ClassFactory.h"

int main(int argc, char** argv)
{
    ...
    std::unique_ptr<Base> myClass = createClass(argv[1])

Big note: All pseudo code.

Then you will have solved the problem of creating a complex set of child classes at runtime and your problem of how to include all of them.

Fantastic Mr Fox
  • 32,495
  • 27
  • 95
  • 175
0

If you want base.h to include sub1.h, that is possible only after the definition of class Base :

#ifndef BASE_H_
#define BASE_H_

class Base
{
    public:
        int name;
};

#include "sub1.h"
#endif

It's obvious that this removes the need for a forward declaration of Base; at the point of inclusion it's fully defined.

MSalters
  • 173,980
  • 10
  • 155
  • 350