Click to See Complete Forum and Search --> : Multiple Inheritance


chanduonline
July 23rd, 2002, 09:48 AM
I have seven classes C1,C2,C3,C4,C5,C6,C7 such that:

1) C2,C3 are derived from C1
2) C4 is derived from C2 and C5 is derived from C3
3) C6 is derived from C2 and C3 (Multiple)
4) C7 is derived from C4, C5 and C6 (Multiple)

Here the question is for which classes I have to derive virtually so that I can aceess a function defined in C1 in C7 with out conflicts.

jfaust
July 23rd, 2002, 10:03 AM
This is just the beginning of your problems, but you want one non-virtual path the the base class. So, try and make C2 or C3 inherit virtually.

Jeff

Bob Davis
July 23rd, 2002, 10:05 AM
That sounds like one heck of a family tree. You may want to rethink your design before you try to get hard into any implementation. If there is any better way to do it, I would recommend going in that direction.

chanduonline
July 23rd, 2002, 10:18 AM
jfaust ,

I have tried that also. The problems with function conflict is not there at this time, some constructor problem is coming. something saying that C1::C1() has problem while compiling the file containg the C7 class (Each class is in separate files and all of them are in one project).


Chandu

jfaust
July 23rd, 2002, 10:23 AM
Chandu,

Actually, I think you want to make both C2 and C3 virtual.

Jeff

chanduonline
July 23rd, 2002, 10:33 AM
Yes,
I have done this

class C2: virtual public C1

class C3: virtual public C1

Graham
July 23rd, 2002, 10:44 AM
Give it up now. Do not go down this route.

jfaust
July 23rd, 2002, 10:56 AM
Graham's completely correct. If this is new development, don't do it. Find a better solution. I guarantee there is one.

These types of hierarchies were much more common in the days when templates were not as well supported as they are now. All-encomposing hierarchies were used so that you could create a container class that maintained pointers to a common base class. Think CObject in MFC.

My point is that if what you are working on already has this hierarchy, it may be too expensive to fix at this point, even if it should be fixed.

Jeff

chanduonline
July 23rd, 2002, 10:58 AM
I am doing this because, I have to go this way only, this classes are generated by some lexical analyzer which compiles files of some format and generate C++ classes for me. So I can make only minor changes to generated files. I can't redesign the class architecture because the tool which generates code is some 3rd partys.

-Chandu

Nikolai Borissov
July 23rd, 2002, 01:28 PM
If I understood you correct, you want to have a single instance of C1 base class in the structure of C7?
Yes, it can be achieved by virtually inheriting both C2 and C3 from C1.
But it's not enough. You have to change initialization of C1 as well.
Virtual base class is initialized by the mostly derived one, i.e. by C7 in your case.
Does C1 have a default constructor?
If not, it must be explicitly initialized in C7 constructor's member initialization list using whatever constructor C1 has.

Nikolai

zdf
July 23rd, 2002, 07:19 PM
The code below works fine. You said something about a C1 default constructor related error. Could you please post the error message(s)?

#include <iostream>

using namespace std;

class C1
{ public: void boo() { cout << "C1::boo" << endl; } };

class C2 : virtual public C1
{};

class C3 : virtual public C1
{};

class C4 : public C2
{};

class C5 : public C3
{};

class C6 : public C2, public C3
{};

class C7 : public C4, public C5
{};

int main()
{
C7().boo();
return 0;
}


Regards,

Nikolai Borissov
July 24th, 2002, 12:55 AM
In your example neither of your classes have
use-defined constructors and, therefore,
implicit default constructors are in effect.
I think these implicit default constructors look like this:

C1(){};
C2():C1(){};
C3():C1(){};
C4():C1(),C2(){};
C5():C1(),C3(){};
C6():C1(),C2(),C3(){};
C7():C1(),C4(),C5(){};

Note that every derived constructor first initializes virtual base class C1.
Actual initialization happens only once in the most derived constructor
(depending on of whatever class the object is declared).
Any other initializations of C1 are ignored.

Things become different when virtual base class C1 contains a non-default constructor.
In this case C1 has no longer a default constructor and MUST be
explicitly initialized in the most derived class.

Here is an example:

#include <iostream>

using namespace std;

class C1
{ public: C1(int i) {}; // non-default constructor
void boo() { cout << "C1::boo" << endl; }
};

class C2 : virtual public C1
{ public: C2():C1(2){}; };

class C3 : virtual public C1
{ public: C3():C1(3){}; };

class C4 : public C2
{ public: C4():C1(4){}; };

class C5 : public C3
{ public: C5():C1(5){}; };

class C6 : public C2, public C3
{};

class C7 : public C4, public C5
{ public: C7():C1(7){}; };

int main()
{
C7().boo();
return 0;
}


Class C7 initializes virtual subobject C1 explicitely now.
Note that C6 does not have that explicit initialization and it compiles OK.
The reason is that no object of C6 is declared.
When object is declared compiler generates an error about C6 class.

Also I discovered that Comeau C++ compiler requires
explicit initialization of C1 in every subobject(C2,C3,C4,C5), even though
when C7 object is declared they are ignored.

Nikolai

zdf
July 24th, 2002, 03:46 AM
Nikolai,
My question was, actually, for chanduonline:

some constructor problem is coming. something saying that C1::C1() has problem while compiling the file containg the C7 class


Sorry!

chanduonline
July 24th, 2002, 04:31 AM
Nikolai Borissov,

Thanks for your detailed explanation. I will try doing that. I don't have a default constructor in any of the classes(All need some initialisation).

zdf,

My error message is
" no match for call: C1* -> C1::C1() "

As 'Nikolai Borissov' said,

I think this because C7 is trying to intialise the C1 constructor with default constructor. But there is no default constructor in C1 that is why it might be giving error. I will try initilising C1 explicitly in C7 constructor.

-Chandu

chanduonline
July 24th, 2002, 05:20 AM
Thanks friends.
The problem got solved by initializing the C1 constructor in C7.


-Chandu