#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! 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
* 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?
<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!
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;
}
=============== ===============
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!!!
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.
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
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. This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
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...
|
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 {}
|
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){;}
};
|
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...
|
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.
| |
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;
...
|
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
|
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;
};
|
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...
|
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...
|
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,...
| |
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...
|
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...
|
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...
|
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...
|
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();...
|
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
| |
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
| |