inheritance and interfaces

Hi everybody

I have a problem working with inheritance and interfaces (classes with pure virtual functions). In the simple example I have an Interface RI and a class RH which both derive from Interface HI. Furthermore a class RJ which inherits from Interface JI and from a class RH. The interface HI has an abstract function "functionA". This function is implemented in class RH. If I try instantiate class RJ I get the following compile error output:


main.cpp(5) : error C2259: 'RJ' : cannot instantiate abstract class
1>        due to following members:
1>        'void HI::functionA(void)' : is abstract
1>        test\hi.h(7) : see declaration of 'HI::functionA'


Why is that so? I am implementing the functionA in class RH which, due to inheritance, should also be in class RJ. I already tried to change the inheritance order in RJ.h but that did not help.
(For a better understanding I also drew a class diagramm, but I could not attached it to this topic. Hope everybody gets it without the diagram.)

Thanks in advance
Rene


main.cpp
1
2
3
4
5
6
#include "RJ.h"

int main()
{
	static RJ rj;
}


RJ.cpp
1
2
3
4
5
6
#include "RJ.h"

RJ::RJ(void)
{
}


RJ.h
1
2
3
4
5
6
7
8
9
10
#ifndef RJ_H
#define RJ_H
#include "JI.h"
#include "RH.h"
class RJ: public JI, public RH
{
public:
	RJ(void);
};
#endif 


JI.cpp
1
2
3
4
5
#include "JI.h"

JI::JI(void)
{
}


JI.h
1
2
3
4
5
6
7
8
9
#ifndef JI_H
#define JI_H
#include "HI.h"
class JI:public HI 
{
public:
	JI(void);
};
#endif 


RH.cpp
1
2
3
4
5
6
7
8
9
#include "RH.h"

RH::RH(void)
{
}

void RH::functionA(void)
{
}


RH.h
1
2
3
4
5
6
7
8
9
10
#ifndef RH_H
#define RH_H
#include "HI.h"
class RH:public HI
{
public:
	RH(void);
	void functionA(void);
};
#endif 


HI.cpp
1
2
3
4
5
#include "HI.h"

HI::HI(void)
{
}


HI.h
1
2
3
4
5
6
7
8
9
#ifndef HI_H
#define HI_H
class HI
{
public:
	HI(void);
	virtual void functionA(void) = 0;
};
#endif 

Last edited on
Function functionA is a pure virtual function - you must redefine it in all or the derived classes. You must redefine functionA in the RJ class.

If this is not what you want, can you make functionA an ordinary virtual function as opposed to a pure one?

Hope all goes well.
Can you please specify what you mean with ordinary and pure virtual function!
Removing the "=0' in HI.h does result in a unresolved external symbols error if that is what you meant.
Last edited on
A pure virtual function has the = 0 on the end. An ordinary virtual function does not. An ordinary virtual function may be redefined.

I should of said that if the function is virtual, you still have to provide a definition of it, preferably in the base class, so that it is inherited. Then change the definition for the derived classes that are different to the others.

Does this clear things up?

Cheers
Ok. so as I understand from your answer there are two solutions:

1st)
redefine the function in all(?) classes. (I think you meant all instantiated classes. So in my case no interfaces.)
So I just changed RJ.cpp and it works!
RJ.cpp
1
2
3
4
5
6
7
8
9
10
#include "RJ.h"

RJ::RJ(void)
{
}

void RJ::functionA(void)
{
	RH::functionA();
}

2nd)
use an ordinary virtual function (no "= 0") and define it in the base class (so in HI.cpp)
I changed to the following.

Hi.cpp
1
2
3
4
5
6
7
8
#include "HI.h"

HI::HI(void)
{
}
void HI::functionA(void)
{
}

Hi.h
1
2
3
4
5
6
7
8
9
#ifndef HI_H
#define HI_H
class HI
{
public:
	HI(void);
	virtual void functionA(void);
};
#endif  
main.cpp
1
2
3
4
5
6
7
8
#include "RJ.h"

int main()
{
	RJ rj;
	rj.functionA();
	getchar();
}


But this does not work I get the error:
main.cpp(6) : error C2385: ambiguous access of 'functionA'
1>        could be the 'functionA' in base 'RH'
1>        or could be the 'functionA' in base 'HI'
1>main.cpp(6) : error C3861: 'functionA': identifier not foun



So the first solution is clear and works. The second is not. I understand the compiler that "now" he does not know which functionA to take. Did I do something wrong here?

Furthermore why didn't it work with my inital approach. I have a pure virtual function in a base class (HI) which derived class is the abstract class or Interface JI. I do not make an instance of JI it is just implemented by RJ to make sure that RJ has to "provide" the functionA. The functionA is then "provided" by the inheritance from RH. So is "providing" by inheritance not enough and does it have to be a real implementation like in Solution 1?

Cheers
class JI:public HI

I just noticed this - That makes a diamond inheritance problem -doesn't it ?

This is solved with virtual class inheritance. Check out this page:

http://en.wikipedia.org/wiki/Virtual_inheritance


No, I do not think that this is the same. It true that the class diagram also looks like a diamond, but in the wiki the function eat, which they are talking about mainly, is declared and defined in the base class Animal.
You could also simplify my problem by moving the pure virtual function declaration from HI to JI and deleting the class HI. This also does not work.

In my case I want to satisfy the interface JI (deriving from HI) "saying" "provide the function functionA" by inheriting from another class RH, which implements it. Shouldn't that be possible?

OK, I am bit confused now.

Could you give the real names of your classes & the function, I might understand better if I can see the real world situation. Can show the inheritance like this:

1
2
3
4
5
6
class HI {};
class RH: public HI {};
class JI: public HI {};
class RJ: public RH, public JI {};



In my case I want to satisfy the interface JI (deriving from HI) "saying" "provide the function functionA" by inheriting from another class RH, which implements it. Shouldn't that be possible?


It has just occurred to me why this might not work. The compiler keeps track of classes with a PTABLE, and virtual functions with a thing called a VTABLE. As I understand it, each derived class maintains a list of pointers to it's base class - this is the PTABLE. Something similar happens for the virtual functions - this is the VTABLE. This is how the compiler can call virtual functions that are defined higher up in the inheritance tree, by following a chain of pointers up the inheritance tree.

So for your situation, can you define functionA in JI rather than RH?


For this error:
main.cpp(6) : error C2385: ambiguous access of 'functionA'
1> could be the 'functionA' in base 'RH'
1> or could be the 'functionA' in base 'HI'
1>main.cpp(6) : error C3861: 'functionA': identifier not found


This is definitely the "Diamond problem" as explained by wiki.

I guess you need to look at why you are doing multiple inheritance. Normally you would do this if you wanted to inherit some of the functionality from class RH say, and different functionality from the other class JI. By having a virtual function in the base class HI, you introduce ambiguity, unless you can use the the scope operator to explicitly call the correct class function. Or use virtual inheritance as per the wiki article.

Last edited on
Topic archived. No new replies allowed.