views:

188

answers:

4

The library I'm using has class G and class S which inherits G.

I needed to add functionality to them, so I wrapped G and S, rather I inherited from them making Gnew and Snew respectively.

So, my inheritance is:

   
 G --> Gnew  
 |      
 v    
 S --> Snew  

But, I want to use Gnew in Snew and when I try to include the Gnew header (in the Snew implementation file) to use it ... the include guards mask the definition of Gnew in Snew???

How can I use Gnew in Snew? Right now, the compiler wont even let me forward declare Gnew in the Snew definition file (which doesn't make sense to me) unless I forward declare inside the class.

In Snew (if I forward declare before the Snew definition) I have:

...
Gnew *g;

The error is:

error: ISO C++ forbids declaration of ‘Gnew’ with no type

If I change Snew to say:

...
class Gnew *g;
Gnew *g;

The error is:

error: invalid use of undefined type ‘struct Snew::Gnew’

NOTE: I was trying to abstract the problem, so I'm closing this and reopening a better phrasing of the question ...

+1  A: 

Where's the cycle? And why would Gnew include the header of Snew?

[Edit] OK, I think your inheritance arrows are opposite of what's customary. But this should get you sorted out:

In Gnew.h:

#pragma once
#if !defined(Gnew_h)
#define Gnew_h

#include "G.h"

class Gnew : public virtual G
{
  // added functionality here.
};

#endif // Gnew_h

In Snew.h:

#pragma once
#if !defined(Snew_h)
#define Snew_h

#include "S.h"
#include "Gnew.h"

class Snew : public virtual Gnew, public virtual S
{
  // added functionality here.
};

#endif // Snew_h

You should not have to forward declare anything.

Note however that this only works as expected if S inherits virtually from G. If all these multiple inheritance issues are too much trouble, you should probably just adapt the library classes instead of inheriting from them.

Does this help?

Tobias
Sorry, it wasn't a cycle, but rather one of the include seems to be masking another ... to be honest I don't quite know.
bias
I include the Gnew header in the Snew implementation file.
bias
If Snew inherits from Gnew, you cannot forward declare Gnew.
Tobias
This breaks another class A, that inherits from Gnew and upcasts from G to A.
bias
How does it break class A? A note on terminology: If A inherits from Gnew and Gnew inherits from G, then a cast from G to A is called a downcast.
Tobias
The library requires that inheritors of G have functions that accept an argument do stuff;} I get the error:cannot convert from base ‘G’ to derived type ‘A’ via virtual base ‘G’
bias
change: A to: A
bias
Well, if that is your only issue you should be able to do this:A* pCastArg = dynamic_cast< A* >(
Tobias
Thanks this resolved the problem.
bias
+1  A: 

Sounds like your include guards are broken somehow. If an include guard triggers, then it should mean that code is already included in the compilation unit. Can you specify the exact error you're getting?

Jherico
I updated the post with the errors.
bias
+2  A: 

This is a perfectly legal case for virtual inheritance. As for the compile errors - make sure those include guards are different in all four headers.

Answering your comment: you need both classes derive virtually. This should really be something like the following:


class G {};
class S: public virtual G {};
class Gnew: public virtual G {};
class Snew: public S, public Gnew {};

This way Snew has only one unambiguous sub-object of class G. I don't know if you control the source for class S, so this might not work for you.

Anyway - inheritance is overrated ;)

Nikolai N Fetissov
So I need to make the library class G a virtual class?
bias
OK ... apparently I need to hit the C++ books again.
bias
+1 for stressing that S needs to to inherit virtually.
Tobias
+2  A: 

Do not include header files into header files when they aren't needed. Just forward declare the type you want to use and include the header file in the .cpp file that needs to know about the implementation of that type (Gnew in this case). The header file doesn't need this information.

// snew.h

// forward declare Gnew
class Gnew;

class Snew : public S
{
    Gnew* gnew;
};

// snew.cpp

#include "gnew.h"

// ..

I dont see the point in using multiple and virtual inheritance. First you have a normal simple inheritance chain like this: G -> S -> Snew. And you want to use Gnew in S but you send G into the constructor of S and do a dynamic_cast to Gnew. Why dont you just send in Gnew directly into the constructor of S? Like this:

SteadyStateDBGA(const Genome& g, const std::string& rootD, 
                const std::string& parName);
Magnus Skog
Actually, this is what I'm doing. I've never had a problem with this before and I'm quite confused.
bias
Please provide us with some more code. It's impossible to deduce the error otherwise. I don't like to guess :)
Magnus Skog
I linked the files. But, it seems like it might be better for me to completely re-ask the question with the actual code. Thanks.
bias