473,240 Members | 1,727 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,240 software developers and data experts.

Multiple inheritance: Wrong constructors being called?

Hi everyone,

I'm having some trouble getting the correct chain of constructors to be called when creating an object at the bottom of a hierarchy. Have a look at the code below - the inheritance goes like this:

Shape
|
+-- Ellipse
|
+-- Circle

When I create a new Circle, it calls the Ellipse's constructor, which in turn calls the Shape's constructor. The problem is that I'm passing parameters to the constructors, and the Ellipse's constructor passes these parameters on to the Shape's constructor - but these parameters are ignored and the Shape's default constructor is called instead of the one taking parameters!

What am I doing wrong???

----------------------------------------------
#include <iostream>

class Shape
{
public:
Shape(void)
{
std::cout << "Default shape constructor, should be unused" << std::endl;
}

Shape(int width, int height)
{
std::cout << "Creating a new shape with size " << width << "x" << height << std::endl;
}
};

class Ellipse: virtual public Shape
{
public:
Ellipse(int width, int height):
Shape(width, height)
{
std::cout << "In Ellipse constructor, a shape with size should have already been created above" << std::endl;
}
};

class Circle: virtual public Ellipse
{
public:
Circle(int width, int height):
Ellipse(width, height)
{
std::cout << "In Circle constructor, Ellipse should already have been created above" << std::endl;
}
};

int main(void)
{
Circle *c = new Circle(10, 20);
delete c;
return 0;
}

----------------------------------------------

$ g++ -o test test.cpp && ./test

Default shape constructor, should be unused
In Ellipse constructor, a shape with size should have already been created above
In Circle constructor, Ellipse should already have been created above

----------------------------------------------

Thanks,
Adam.
Mar 11 '07 #1
7 3690
Adam Nielsen wrote:
Hi everyone,

I'm having some trouble getting the correct chain of constructors to be called when creating an object at the bottom of a hierarchy. Have a look at the code below - the inheritance goes like this:

Shape
|
+-- Ellipse
|
+-- Circle

When I create a new Circle, it calls the Ellipse's constructor, which in turn calls the Shape's constructor. The problem is that I'm passing parameters to the constructors, and the Ellipse's constructor passes these parameters on to the Shape's constructor - but these parameters are ignored and the Shape's default constructor is called instead of the one taking parameters!

What am I doing wrong???
Using virtual inheritance. Drop the virtual and everything will work as
you expect.

john
Mar 11 '07 #2
Using virtual inheritance. Drop the virtual and everything will work
as you expect.
Ah yes, that worked. I think I'll need to re-think the virtual
inheritance in the rest of my code... :-/

Thanks for your help!

Cheers,
Adam.
Mar 11 '07 #3
Adam Nielsen wrote:
Hi everyone,

I'm having some trouble getting the correct chain of constructors to be called when creating an object at the bottom of a hierarchy. Have a look at the code below - the inheritance goes like this:

Shape
|
+-- Ellipse
|
+-- Circle

When I create a new Circle, it calls the Ellipse's constructor, which in turn calls the Shape's constructor. The problem is that I'm passing parameters to the constructors, and the Ellipse's constructor passes these parameters on to the Shape's constructor - but these parameters are ignored and the Shape's default constructor is called instead of the one taking parameters!

What am I doing wrong???
BTW making a circle inherit from an ellipse is a classic mistake in OO
programming, see here

http://en.wikipedia.org/wiki/Circle-ellipse_problem

Speculating from the code you've posted I would guess that you've
misunderstood the concept of multiple inheritance. Multiple inheritance
means a class having more than one *direct* base class. And there are
situations using multiple inheritance when you also need to use virtual
inheritance, and yes it does change the rules for how constructors are
called.

However multiple inheritance does not mean having an inheritance
hierarchy with a depth of greater than one. That is what the code you
posted has, but it is still simple single inheritance.

john
Mar 11 '07 #4
On 11 Mar, 07:56, Adam Nielsen <a.niel...@shikadi.rem.ove.netwrote:
Hi everyone,

I'm having some trouble getting the correct chain of constructors to be called when creating an object at the bottom of a hierarchy. Have a look at the code below - the inheritance goes like this:

Shape
|
+-- Ellipse
|
+-- Circle

When I create a new Circle, it calls the Ellipse's constructor, which in turn calls the Shape's constructor. The problem is that I'm passing parameters to the constructors, and the Ellipse's constructor passes these parameters on to the Shape's constructor - but these parameters are ignored and the Shape's default constructor is called instead of the one taking parameters!

What am I doing wrong???

----------------------------------------------
#include <iostream>

class Shape
{
public:
Shape(void)
{
std::cout << "Default shape constructor, should be unused" << std::endl;
}

Shape(int width, int height)
{
std::cout << "Creating a new shape with size " << width << "x" << height << std::endl;
}

};

class Ellipse: virtual public Shape
{
public:
Ellipse(int width, int height):
Shape(width, height)
{
std::cout << "In Ellipse constructor, a shape with size should have already been created above" << std::endl;
}

};

class Circle: virtual public Ellipse
{
public:
Circle(int width, int height):
Ellipse(width, height)
{
std::cout << "In Circle constructor, Ellipse should already have been created above" << std::endl;
}

};

int main(void)
{
Circle *c = new Circle(10, 20);
delete c;
return 0;

}

----------------------------------------------

$ g++ -o test test.cpp && ./test

Default shape constructor, should be unused
In Ellipse constructor, a shape with size should have already been created above
In Circle constructor, Ellipse should already have been created above

----------------------------------------------

Thanks,
Adam.
Hiya,

In C++, when you create an instance of a class, virtual base class
constructors are called first. If you don't have an explicit call to
a virtual base class ctor, then the compiler will call it under the
covers *and will use the default [no parameter] constructor*. If you
want it to call a non-default ctor, you must make an explicit call to
the ctor in the initializer list.

So, your Circle has two virtual base classes - Ellipse and Shape. The
standard says that these base classes should be constructed in left-to-
right order depth first search. In your case, that means the compiler
will want to initialize Shape first, then Ellipse. The compiler sees
that you haven't specified an explicit initializer call to a Shape
ctor, so it adds in a call to the default ctor for you.

So, if you add the following to your Circle ctor initializer list:

public:
Circle(int width, int height):
>> Shape(width, height), <<<
Ellipse(width, height)
{

then you end up with what you wanted.

Hope that helps,
Doug

Mar 11 '07 #5
Hi John,
BTW making a circle inherit from an ellipse is a classic mistake in OO
programming
Speculating from the code you've posted I would guess that you've
misunderstood the concept of multiple inheritance.
This code was just an example to illustrate the problem - my real code
is different, but you may have a point. I was using each subclass to
represent a more specific case of each parent (in the same way that an
Ellipse is a more specific version of a Shape.)

This may not be the best way of doing things, but in my particular case
it's certainly the easiest :-)
Multiple inheritance means a class having more than one *direct* base
class. And there are situations using multiple inheritance when you
also need to use virtual inheritance, and yes it does change the rules
for how constructors are called. However multiple inheritance does
not mean having an inheritance hierarchy with a depth of greater than
one. That is what the code you posted has, but it is still simple
single inheritance.
Eventually later on in the program I do use multiple inheritance
properly (e.g. a class may inherit both an Ellipse and a Rectangle,
which would give it two copies of the Shape base class) however having
said that these particular classes will never be multiply inherited - so
there was no need for virtual inheritance here after all (but when
you're still not 100% familiar with the concepts, a rule of thumb like
making all inheritance virtual is really tempting!)

Cheers,
Adam.
Mar 11 '07 #6
Hi Doug,
In C++, when you create an instance of a class, virtual base class
constructors are called first.
Yes, I now realise why that happens.
So, if you add the following to your Circle ctor initializer list:

public:
Circle(int width, int height):
> Shape(width, height), <<<
Ellipse(width, height)
{

then you end up with what you wanted.
I had thought about something like that when the problem was first
pointed out, but I was somewhat reluctant to do it this way - the Circle
isn't really supposed to be aware of the Shape, it's only supposed to
know about the workings of its direct parent class, the Ellipse.

Thanks for your suggestion though!

Cheers,
Adam.
Mar 11 '07 #7
On 11 Mar, 21:57, Adam Nielsen <a.niel...@shikadi.rem.ove.netwrote:
Hi Doug,
In C++, when you create an instance of a class, virtual base class
constructors are called first.

Yes, I now realise why that happens.
So, if you add the following to your Circle ctor initializer list:
public:
Circle(int width, int height):
>> Shape(width, height), <<<
Ellipse(width, height)
{
then you end up with what you wanted.

I had thought about something like that when the problem was first
pointed out, but I was somewhat reluctant to do it this way - the Circle
isn't really supposed to be aware of the Shape, it's only supposed to
know about the workings of its direct parent class, the Ellipse.

Thanks for your suggestion though!

Cheers,
Adam.
Hi Adam,

Totally fair play, mate. I wouldn't have done it either.

Doug

Mar 12 '07 #8

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Alexander Stippler | last post by:
I've got an inheritance structure with two coupled "dreaded diamonds" like shown below: A / \ / \ B C \ / \ \ / \ D E \ /
4
by: Busin | last post by:
When a child class inherits from a base class, will the child class inherits everything of the base class, including all member variables and functions? Or is such inheritance "selective", like not...
3
by: Gianni Mariani | last post by:
In the code below, controller::controller() is never invoked, however, it appears there is no way to make a compile-time rule that this should not happen. The code below seems to make compilers...
4
by: Xavier | last post by:
Hi, I have a question, in a "dreaded diamond" situation, regarding the following code: ---- Begin code #include <iostream> using namespace std;
22
by: Matthew Louden | last post by:
I want to know why C# doesnt support multiple inheritance? But why we can inherit multiple interfaces instead? I know this is the rule, but I dont understand why. Can anyone give me some concrete...
45
by: Ben Blank | last post by:
I'm writing a family of classes which all inherit most of their methods and code (including constructors) from a single base class. When attempting to instance one of the derived classes using...
5
by: Thomas Girod | last post by:
Hi. I think I'm missing something about multiple inheritance in python. I've got this code. class Foo: def __init__(self): self.x = "defined by foo" self.foo = None
8
by: Robert | last post by:
Hi! So far I have been doing "inheritance" in Javascript like this: ****** function TestObject(value) { this.value = value; }
3
by: Jess | last post by:
Hello, I've been reading Effective C++ about multiple inheritance, but I still have a few questions. Can someone give me some help please? First, it is said that if virtual inheritance is...
0
by: jianzs | last post by:
Introduction Cloud-native applications are conventionally identified as those designed and nurtured on cloud infrastructure. Such applications, rooted in cloud technologies, skillfully benefit from...
0
by: abbasky | last post by:
### Vandf component communication method one: data sharing ​ Vandf components can achieve data exchange through data sharing, state sharing, events, and other methods. Vandf's data exchange method...
0
Git
by: egorbl4 | last post by:
Скачал я git, хотел начать настройку, а там вылезло вот это Что это? Что мне с этим делать? ...
0
by: MeoLessi9 | last post by:
I have VirtualBox installed on Windows 11 and now I would like to install Kali on a virtual machine. However, on the official website, I see two options: "Installer images" and "Virtual machines"....
0
by: DolphinDB | last post by:
The formulas of 101 quantitative trading alphas used by WorldQuant were presented in the paper 101 Formulaic Alphas. However, some formulas are complex, leading to challenges in calculation. Take...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: Aftab Ahmad | last post by:
So, I have written a code for a cmd called "Send WhatsApp Message" to open and send WhatsApp messaage. The code is given below. Dim IE As Object Set IE =...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.