473,656 Members | 2,983 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

virtual inheritance downcast

#include <iostream>
using namespace std;

class Base
{
public:
Base() {}
~Base() {}
};

class Derived : virtual public Base
{
public:
Derived() {}
~Derived() {}
};

int main()
{
Base *b = new Derived();
Derived *d = (Derived*)b; //line 22. The problem line!

return 0;
}

For the code above, I got the following error message:
downcast.cc: In function `int main()':
downcast.cc:22: error: cannot convert from base `Base' to derived type `
Derived' via virtual base `Base'

That means it is illegal to explicit convert a VIRTUAL base point to the
derived point. (non-virtual is ok) Can somebody explain it? ( The coding
style is bad, please just ignore it. ^_^)

Thanks in advance!
Apr 19 '06 #1
8 12653
fl****@gmail.co m wrote:
#include <iostream>
using namespace std;

class Base
{
public:
Base() {}
~Base() {}
};

class Derived : virtual public Base
{
public:
Derived() {}
~Derived() {}
};

int main()
{
Base *b = new Derived();
Derived *d = (Derived*)b; //line 22. The problem line!

return 0;
}

For the code above, I got the following error message:
downcast.cc: In function `int main()':
downcast.cc:22: error: cannot convert from base `Base' to derived type `
Derived' via virtual base `Base'

That means it is illegal to explicit convert a VIRTUAL base point to the
derived point. (non-virtual is ok) Can somebody explain it? ( The coding
style is bad, please just ignore it. ^_^)


The compiler is correct - the conversion is illegal. Equivalently (and
more specifically), you cannot downcast a virtual base class pointer to
a derived class pointer using static_cast. This is because the case may
involve some pointer adjustment that depends on the dynamic type of the
object pointed to. e.g.

class Base
{
char i;
};

class Derived : virtual public Base
{
int j
};

class Derived2 : virtual public Base
{
int k;
};

class DiamondBottom: public Derived, public Derived2
{
int l;
};

int main()
{
Base *b = new DiamondBottom() ;
Derived *d = static_b; //line 22. The problem line!

return 0;
}

Now, in a DiamondBottom object, the Derived2 subobject is likely to be
placed after the Derived subobject, which means that the pointer
adjustment required for a conversion from a Base* to a Derived2* depends
on whether the Derived2 is part of a larger DiamondBottom object or not.

E.g. a Derived2 object looks like this (vtable pointers left out):
i
k

while a DiamondBotton object might look like this (vtable pointers left
out):
i
j
k
l

so that i and k are in different relative positions depending on the
dynamic type of the object.

The solution is to use dynamic_cast, which performs the correct
conversion by checking the real type of the object.

Tom
Apr 19 '06 #2
* fl****@gmail.co m:
#include <iostream>
using namespace std;

class Base
{
public:
Base() {}
~Base() {}
};

class Derived : virtual public Base
{
public:
Derived() {}
~Derived() {}
};

int main()
{
Base *b = new Derived();
Derived *d = (Derived*)b; //line 22. The problem line!
Yes, don't use C-style casts. A C-style cast tells the compiler that
your Really Know What You're Doing. Which you absolutely don't, here.

return 0;
}

For the code above, I got the following error message:
downcast.cc: In function `int main()':
downcast.cc:22: error: cannot convert from base `Base' to derived type `
Derived' via virtual base `Base'

That means it is illegal to explicit convert a VIRTUAL base point to the
derived point. (non-virtual is ok) Can somebody explain it? ( The coding
style is bad, please just ignore it. ^_^)


Due to the virtual inheritance the Base sub-object can be a shared Base
sub-object for any number of Derived objects. So which one should the
cast produce a pointer to? There's no way to tell, strictly locally,
from the static type information, and for consistency the rules don't
distinguis situations like above where the compiler /could/ have figured
it out by looking at the rest of the program text.

So to do this you need access to run time type information, what the
object really is when the cast is attempted, and you need to allow for
failure.

And to do that, use a dynamic_cast (which requires at least one virtual
member function in Base, e.g. the destructor).

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
Apr 19 '06 #3

<fl****@gmail.c om> wrote in message news:e2******** **@news.cn99.co m...
#include <iostream>
using namespace std;

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

class Derived : virtual public Base
{
public:
Derived() {}
~Derived() {}
};

int main()
{
Base *b = new Derived();
Derived *d = (Derived*)b; //line 22. The problem line! Derived *d = dynamic_cast<De rived *>(b);

if you don't have virtual members in base class, then you can't use
dynamic_cast. In that case, reinterpret_cas t is the only option but it will
cause undefined behavior on some platform...
return 0;
}

For the code above, I got the following error message:
downcast.cc: In function `int main()':
downcast.cc:22: error: cannot convert from base `Base' to derived type `
Derived' via virtual base `Base'

That means it is illegal to explicit convert a VIRTUAL base point to the
derived point. (non-virtual is ok) Can somebody explain it? ( The coding
style is bad, please just ignore it. ^_^)

Thanks in advance!

Apr 21 '06 #4
Fei Liu wrote:
dynamic_cast. In that case, reinterpret_cas t is the only option but it will
cause undefined behavior on some platform...


The reinterpret_cas t creates a value of a new type that has the SAME
BIT pattern as its argument so it will cause undefined behavior in ANY
platform, not some platforms from the base class to the derived class.

FYI, here is a test case:
=============== =======
#include <iostream>
using namespace std;

class Base
{
public:
float base_v;
Base(): base_v(999) { }
~Base() {}

};

class Derived : virtual public Base
{
public:
int derived_v;
Derived(): derived_v(0) {}
~Derived() {}

};

int main()
{
Base *b = new Derived();
Derived *d = reinterpret_cas t<Derived *>(b); //line 22. The
problem line!

cout << "b->base_v=" << b->base_v << endl;

//d->derived_v shows a weired result
cout << "d->derived_v=" << d->derived_v << endl;

// the following will throw segamentation fault!
cout << "d->base_v=" << d->base_v << endl;

return 0;
}
=============== ===============

Apr 21 '06 #5
dan2online wrote:
dynamic_cast. In that case, reinterpret_cas t is the only option but it
will
cause undefined behavior on some platform...
The reinterpret_cas t creates a value of a new type that has the SAME
BIT pattern as its argument so it will cause undefined behavior in ANY
platform, not some platforms from the base class to the derived class.


....
class Derived : virtual public Base


Nice sample, but if you take the 'virtual' out, then on some platforms the
address of the Derived will be the same as the address of the Base within
it. You can assert for that.

In that situation, this rule takes effect: "reinterpret_ca st works correctly
if it casts a pointer or reference to a type that an address truly
contains".

(Someone will doubtless look the correct verbiage up for me: My copy of the
old Standard is on my old hard drives.)

So in that narrow situation the behavior is defined.

--
Phlip
http://www.greencheese.org/ZeekLand <-- NOT a blog!!!
Apr 21 '06 #6

Phlip wrote:
dan2online wrote:

Nice sample, but if you take the 'virtual' out, then on some platforms the
address of the Derived will be the same as the address of the Base within
it. You can assert for that.


If the "virtual" disappears, the original example has no problem then.

Apr 21 '06 #7
Phlip wrote:
dan2online wrote:
dynamic_cast. In that case, reinterpret_cas t is the only option but it
will
cause undefined behavior on some platform...


The reinterpret_cas t creates a value of a new type that has the SAME
BIT pattern as its argument so it will cause undefined behavior in ANY
platform, not some platforms from the base class to the derived class.

class Derived : virtual public Base


Nice sample, but if you take the 'virtual' out, then on some platforms the
address of the Derived will be the same as the address of the Base within
it. You can assert for that.


If you leave the virtual in, it might still be the case. Of course, you
can't
compare a Derived* and a Base*; so for your assert you'd still need to
cast the other side of the comparison as well (or the first side back,
depending on how you write the assert). So the assert may cause
undefined behavior; it's a bit tricky to say without code.

Still, IIRC it's not the creation of the Derived* that will trip you,
but the actual
use as if it indeed points to a Derived*. You should be able to cast it
back to
the original Base*. Not very useful, I admit.

This doesn't matter a lot when it comes to Undefined Behavior and
platforms.
Undefined Behavior is what the ISO standard says about a piece of code.

If it's UB according to the standard, it's UB for all compilers, and if
not, for none.
(Disregarding trivial code like const int i = 4/sizeof(int)-4. A
division by zero is
still UB everywhere)

HTH,
Michiel Salters

Apr 21 '06 #8
Fei Liu wrote:

if you don't have virtual members in base class, then you can't use
dynamic_cast. In that case, reinterpret_cas t is the only option but it will
cause undefined behavior on some platform...

Actually the C-style cast here will do a static_cast. This isn't
undefined as long as you know that the dynamic type really is
the type being cast to.
Apr 27 '06 #9

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

Similar topics

6
6468
by: Stuart Golodetz | last post by:
Hi, I've got a minor casting issue which I need to check about (marked // <--). I was trying to do a static_cast on it (which didn't work, though I'm not sure why this should be the case?) I also tried reinterpret_cast (which is clearly an exceedingly dodgy thing to do; it worked, but I'm not sure whether it should have worked, or whether (the more likely scenario) it was just coincidence?) Finally, after a bit of trawling through the...
4
2890
by: JKop | last post by:
I'm starting to think that whenever you derive one class from another, that you should use virtual inheritance *all* the time, unless you have an explicit reason not to. I'm even thinking that there shouldn't have been a "virtual" keyword for this purpose, but instead, a "nonvirtual" keyword! In teaching inheritance, you see the common example: class Vehicle {}
14
1915
by: Bruno van Dooren | last post by:
Hi all, i am having a problems with inheritance. consider the following: class A { public: A(int i){;} };
9
1133
by: Joe | last post by:
Hello All: I work at an insurance company and we are changing the design of an ASP.NET application (for those have followed my postings, we're going to redesign some parts of the application - thank you Kevin and Bruce!). The application processes claims. We have two types of claims, PClaim and WClaim (property claims and worker's comp claims). PClaim and WClaim share some common traits so I can have them inherit from an abstract...
3
1707
by: Imre | last post by:
Hi! I've got some questions regarding heavy use of virtual inheritance. First, let's see a theoretical situation, where I might feel tempted to use a lot of virtual inheritance. Let's suppose, we're creating a little strategy game. In our game, there are Units. A Unit can be either a Human, or a Vehicle. Obviously, Human and Vehicle are subclasses of Unit.
8
2174
by: Alex Vinokur | last post by:
Here is a code from http://www.parashift.com/c++-faq-lite/virtual-functions.html#faq-20.8 -------------------------------------- class Shape { public: virtual ~Shape() { } // A virtual destructor virtual void draw() = 0; // A pure virtual function virtual void move() = 0; ...
3
4547
by: kikazaru | last post by:
Is it possible to return covariant types for virtual methods inherited from a base class using virtual inheritance? I've constructed an example below, which has the following structure: Shape = base class Triangle, Square = classes derived from Shape Prism = class derived from Shape TriangularPrism, SquarePrism = classes derived from Triangle and Prism, or Square and Prism respectively
23
4599
by: Dave Rahardja | last post by:
Since C++ is missing the "interface" concept present in Java, I've been using the following pattern to simulate its behavior: class Interface0 { public: virtual void fn0() = 0; };
0
1304
by: =?Utf-8?B?Zmplcm9uaW1v?= | last post by:
Hi all, As I mentioned in a previous thread (see 'Dbghelp, symbols and templates' in microsoft.public.windbg), we created a powerful symbol engine using dbghelp to dump the contents of the stack symbols when an exception occurs. The engine is able to dereference and process UDT symbols up to their highest base class. It also supports multiple inheritance. However, we are having trouble with virtual inheritance. Documentation is very...
0
8380
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, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
8296
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
8816
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...
0
8710
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven tapestry of website design and digital marketing. It's not merely about having a website; it's about crafting an immersive digital experience that captivates audiences and drives business growth. The Art of Business Website Design Your website is...
0
8598
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
6162
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
5627
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();...
1
2721
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
1928
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.