473,790 Members | 3,200 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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 1450
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::add Device(Interfac e *) 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(Inter face *) 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
4339
by: Graham Banks | last post by:
Does using multiple inheritance introduce any more performance overhead than single inheritance?
5
2183
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 multiple inheritance still be avoided? If yes, why multiple inheritance is introducted into C++?
20
10087
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 advance for enlightment ... here's the snippet #!/usr/bin/python
22
23385
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 examples?
47
3653
by: Mark | last post by:
why doesn't .NET support multiple inheritance? I think it's so silly! Cheers, Mark
60
4944
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 'target' programming community herein) to get some community input and verify (or not) the following two statements. Few programmers (3 to7%) UNDERSTAND 'Strategic Functional Migration
15
28377
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 an error saying you are not allowed Multiple base classes. /// <summary>
7
3741
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 goes like this: Shape | +-- Ellipse | +-- Circle
47
4043
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 support multiple inheritance. In C++ for instance I noticed that the compiler flags an error if you use the "ref" keyword on a class with multiple base classes. This supports the above quote. However, under the "CodeClass2.Bases" property (part...
0
9512
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 effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10419
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
10147
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9023
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
1
7531
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6770
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5424
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5552
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
2
3709
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

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.