473,385 Members | 1,908 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,385 software developers and data experts.

multiple inheritance oddnes

This is a condensed version of a problem I came across today, can
anyone explain what is going on?

If the code below is run nothing will be output (in the original
problem it was causing exeptions).

if all the virtual destructors are commented out it outputs 'e'
or if
"class InterfaceImpl : public Base, public Interface"
is changed to
"class InterfaceImpl : public Interface, public Base"
it also outputs 'e'

in the default case (ie that below) *p refers to a "Base" then
p->recvSignal() causes the problem. Why is it not referring to an
"Interface". And to me more strangely why does it then refer to an
"Interface" if the virtual destructors are removed?

Thanks in advance for any responses - it will probably be monday before
I get to look at them.

Also at the moment the problem has been worked around simply by
altering the order of the inherited classes as noted above. Is this
safe?

#include <iostream>
using namespace std;

class Interface
{
public:
virtual void recvSignal(char ch) = 0;
virtual ~Interface(){};
};

class Controller
{
public:
void doit()
{
p->recvSignal('e');
};
void addDevice(void* ptr)
{
p = (Interface*)ptr;
};
virtual ~Controller(){};

private:
Interface* p;
};

class Base
{
public:
void nv(){};
virtual ~Base(){};
};

class InterfaceImpl : public Base, public Interface
{
public:
void recvSignal(char ch)
{
cout<<ch<<endl;
};
virtual ~InterfaceImpl(){};
};

class Controlled : public InterfaceImpl
{
public:
void nvgb(){};
virtual ~Controlled(){};
};

int main()
{
Controller ctrl;
Controlled device;

ctrl.addDevice(&device);
ctrl.doit();

return 0;
}

Jul 28 '06 #1
3 1425
dice wrote:
This is a condensed version of a problem I came across today, can
anyone explain what is going on?

If the code below is run nothing will be output (in the original
problem it was causing exeptions).

if all the virtual destructors are commented out it outputs 'e'
or if
"class InterfaceImpl : public Base, public Interface"
is changed to
"class InterfaceImpl : public Interface, public Base"
it also outputs 'e'

[..]
Also at the moment the problem has been worked around simply by
altering the order of the inherited classes as noted above. Is this
safe?
Absolutely not.
#include <iostream>
using namespace std;

class Interface
{
public:
virtual void recvSignal(char ch) = 0;
virtual ~Interface(){};
};

class Controller
{
public:
void doit()
{
p->recvSignal('e');
};
void addDevice(void* ptr)
{
p = (Interface*)ptr;
This cast here is BOGUS, and the source of your error. Rework it
_without_ a C-style cast, and you will find THE RIGHT WAY(tm).
};
virtual ~Controller(){};

private:
Interface* p;
};

class Base
{
public:
void nv(){};
virtual ~Base(){};
};

class InterfaceImpl : public Base, public Interface
{
public:
void recvSignal(char ch)
{
cout<<ch<<endl;
};
virtual ~InterfaceImpl(){};
};

class Controlled : public InterfaceImpl
{
public:
void nvgb(){};
virtual ~Controlled(){};
};

int main()
{
Controller ctrl;
Controlled device;

ctrl.addDevice(&device);
ctrl.doit();

return 0;
}
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Jul 28 '06 #2
dice wrote:
This is a condensed version of a problem I came across today, can
anyone explain what is going on?
...
class Controller
{
public:
void doit()
{
p->recvSignal('e');
};
void addDevice(void* ptr)
{
p = (Interface*)ptr;
};
virtual ~Controller(){};

private:
Interface* p;
};

class Base
{
public:
void nv(){};
virtual ~Base(){};
};

class InterfaceImpl : public Base, public Interface
{
public:
void recvSignal(char ch)
{
cout<<ch<<endl;
};
virtual ~InterfaceImpl(){};
};

class Controlled : public InterfaceImpl
{
public:
void nvgb(){};
virtual ~Controlled(){};
};

int main()
{
Controller ctrl;
Controlled device;

ctrl.addDevice(&device);
ctrl.doit();

return 0;
}
The above 'addDevice' call will convert a pointer of type 'Controlled*' to a
pointer of type 'Interface*' through an intermediate type 'void*':

Controlled* -void* -Interface*

This will not produce a usable 'Interface*' value in general case. The direct
conversion

Controlled* -Interface*

would work fine, of course, but that 'void*' in the middle destroys everything,
because it hides the relationship between the source and target pointers from
the compiler.

If you really need that intermediate 'void*' (why?), then changing the order of
multiple bases is not a good workaround (this won't solve anything in the long
run). One way to deal with it is to perform the 'Controlled* -Interface*'
conversion explicitly before you convert to 'void*'

// in main()
ctrl.addDevice((Interface*) &device);

This will work regardless of the order of base classes. But, once again, the
better way to solve it is to get rid of that 'void*' entirely. Why do you need
it anyway?

--
Best regards,
Andrey Tarasevich
Jul 28 '06 #3

Andrey Tarasevich wrote:
dice wrote:
This is a condensed version of a problem I came across today, can
anyone explain what is going on?
...
class Controller
{
public:
void doit()
{
p->recvSignal('e');
};
void addDevice(void* ptr)
{
p = (Interface*)ptr;
};
virtual ~Controller(){};

private:
Interface* p;
};

class Base
{
public:
void nv(){};
virtual ~Base(){};
};

class InterfaceImpl : public Base, public Interface
{
public:
void recvSignal(char ch)
{
cout<<ch<<endl;
};
virtual ~InterfaceImpl(){};
};

class Controlled : public InterfaceImpl
{
public:
void nvgb(){};
virtual ~Controlled(){};
};

int main()
{
Controller ctrl;
Controlled device;

ctrl.addDevice(&device);
ctrl.doit();

return 0;
}

The above 'addDevice' call will convert a pointer of type 'Controlled*' to a
pointer of type 'Interface*' through an intermediate type 'void*':

Controlled* -void* -Interface*

This will not produce a usable 'Interface*' value in general case. The direct
conversion

Controlled* -Interface*

would work fine, of course, but that 'void*' in the middle destroys everything,
because it hides the relationship between the source and target pointers from
the compiler.

If you really need that intermediate 'void*' (why?), then changing the order of
multiple bases is not a good workaround (this won't solve anything in the long
run). One way to deal with it is to perform the 'Controlled* -Interface*'
conversion explicitly before you convert to 'void*'

// in main()
ctrl.addDevice((Interface*) &device);

This will work regardless of the order of base classes. But, once again, the
better way to solve it is to get rid of that 'void*' entirely. Why do you need
it anyway?
in the original real problem addDevice(void*) is actually called from
within a device object as ctrl.addDevice(this). The idea was that the
function should be Controller::addDevice(Interface *) but when this
would not compile stating something along the lines that the cast
"exists but is not accessible" addDevice was changed to use void*
triggering the current badness. I cannot give the exact error as I
dont have access to the code at the moment but it was as if the base
class implementation was somehow hidden - though they are all public in
the declarations. I will give a more exact desctiption of the error
when trying to use addDevice(Interface *) on monday.
>
--
Best regards,
Andrey Tarasevich
Jul 29 '06 #4

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

Similar topics

2
by: Graham Banks | last post by:
Does using multiple inheritance introduce any more performance overhead than single inheritance?
5
by: Morgan Cheng | last post by:
It seems no pattern defined by GoF takes advantage of multiple inheritance. I am wondering if there is a situation where multiple inheritance is a necessary solution. When coding in C++, should...
20
by: km | last post by:
Hi all, In the following code why am i not able to access class A's object attribute - 'a' ? I wishto extent class D with all the attributes of its base classes. how do i do that ? thanks in...
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...
47
by: Mark | last post by:
why doesn't .NET support multiple inheritance? I think it's so silly! Cheers, Mark
60
by: Shawnk | last post by:
Some Sr. colleges and I have had an on going discussion relative to when and if C# will ever support 'true' multiple inheritance. Relevant to this, I wanted to query the C# community (the...
15
by: iKiLL | last post by:
hi all, I would like to be able to create an umbrella class for all my main global sections but I would still like to keep them all in separate file something like the below but I keep getting...
7
by: Adam Nielsen | last post by:
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...
47
by: Larry Smith | last post by:
I just read a blurb in MSDN under the C++ "ref" keyword which states that: "Under the CLR object model, only public single inheritance is supported". Does this mean that no .NET class can ever...
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...

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.