473,569 Members | 2,845 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Bogus cast from class to totally unrelated class works - why?

Hello All,

I did try searching the archives, but the topics seemed to be mostly
about base
and derived classes.

I have reached Chapter 8 in Bruce Eckel's "Thinking in C++ 2nd Edition
Vol. 1".
Question 28 says:

"Create a class called bird that can fly( ) and a class rock that
can't. Create
a rock object, take its address, and assign that to a void*. Now take
the void*,
assign it to a bird* (you'll have to use a cast), and call fly( )
through that
pointer. Is it clear why C's permission to openly assign via a void*
(without a cast) is a "hole" in the language, which couldn't be
propagated
into C++?"

I came up with:

#include <iostream>
using namespace std;

class Bird{
public:
void fly(){ cout << "Flying..." << endl; }
};

class Rock{
double d;
};

int main()
{
Rock r;
void *v = &r;
Bird *pb = reinterpret_cas t<Bird*>(v);
pb->fly();
return 0;
}

This compiled and linked without warnings, as I expected. I understand
why
you should not be allowed to convert a Rock to a Bird (unless you
really, really
want to very badly).

What I did *not* expect was that it would run, but it did. Why don't
I get
a run-time error when I call fly() in my Rock masquerading as a Bird?

I tried it with gcc 3.4.2 (MingW Windows port) and 4.1.1
(http://oss.netfarm.it/mplayer-win32.php) and it worked in both cases.
I am on Windows XP SP2.

May 13 '07 #1
5 1888
On 13 May, 19:15, johnbrown...@ho tmail.com wrote:
Hello All,

I did try searching the archives, but the topics seemed to be mostly
about base
and derived classes.

I have reached Chapter 8 in Bruce Eckel's "Thinking in C++ 2nd Edition
Vol. 1".
Question 28 says:

"Create a class called bird that can fly( ) and a class rock that
can't. Create
a rock object, take its address, and assign that to a void*. Now take
the void*,
assign it to a bird* (you'll have to use a cast), and call fly( )
through that
pointer. Is it clear why C's permission to openly assign via a void*
(without a cast) is a "hole" in the language, which couldn't be
propagated
into C++?"

I came up with:

#include <iostream>
using namespace std;

class Bird{
public:
void fly(){ cout << "Flying..." << endl; }

};

class Rock{
double d;

};

int main()
{
Rock r;
void *v = &r;
Bird *pb = reinterpret_cas t<Bird*>(v);
pb->fly();
return 0;

}

This compiled and linked without warnings, as I expected. I understand
why
you should not be allowed to convert a Rock to a Bird (unless you
really, really
want to very badly).

What I did *not* expect was that it would run, but it did. Why don't
I get
a run-time error when I call fly() in my Rock masquerading as a Bird?

I tried it with gcc 3.4.2 (MingW Windows port) and 4.1.1
(http://oss.netfarm.it/mplayer-win32.php) and it worked in both cases.
I am on Windows XP SP2.
Well the behaviour is undefined so the compiler is allowed to do
anything it wants and from a language definition point of view no
outcome is more or less valid than any other. But what is probably
happening is:

fly() is a member function of Bird and so your compiler creates code
exactly as it would for a normal function, except it inserts an extra
parameter of type Bird*. This extra parameter is the implied this
pointer that every (non-static) member function of any class has but
that does not appear explicitly in the parameter list. Now, in your
code, the Bird* this pointer inside fly() actually points to a Rock
and so any attempt to use or dereference the pointer isn't going to
work. But none of the code in your fly() function actually uses the
this pointer - no other member functions of Bird are called and no
member data is touched. Try changing the definition of Bird as below
and you might see something more obviously strange. Watch out for
nasal demons.

class Bird{
public:
Bird() : wbpm(42) {}
void fly()
{
cout << "Flying at " << this->wbpm << " wing beats per
minute" << endl;
}
private:
int wbpm;
};

Gavin Deane

May 13 '07 #2
On May 13, 2:15 pm, johnbrown...@ho tmail.com wrote:
Hello All,

I did try searching the archives, but the topics seemed to be mostly
about base
and derived classes.

I have reached Chapter 8 in Bruce Eckel's "Thinking in C++ 2nd Edition
Vol. 1".
Question 28 says:

"Create a class called bird that can fly( ) and a class rock that
can't. Create
a rock object, take its address, and assign that to a void*. Now take
the void*,
assign it to a bird* (you'll have to use a cast), and call fly( )
through that
pointer. Is it clear why C's permission to openly assign via a void*
(without a cast) is a "hole" in the language, which couldn't be
propagated
into C++?"

I came up with:

#include <iostream>
using namespace std;

class Bird{
public:
void fly(){ cout << "Flying..." << endl; }

};

class Rock{
double d;

};

int main()
{
Rock r;
void *v = &r;
Bird *pb = reinterpret_cas t<Bird*>(v);
pb->fly();
return 0;

}

This compiled and linked without warnings, as I expected. I understand
why
you should not be allowed to convert a Rock to a Bird (unless you
really, really
want to very badly).
You aren't converting a Rock to a bird, you are 'reinterpreting ' a
Rock* to a void* and that to a Bird*.
Converting a pointer converts the pointer, not its pointee.
Did you not read the warnings about using reinterpret_cas t?
An old type cast might very well apply a static_cast, a dynamic_cast
or a reinterpret_cas t.
You had no control over which was employed. Now you do.

int main()
{
Rock r;
Bird *pb = static_cast<Bir d*>(&r); // invalid cast
pb->fly();
return 0;
}

Again, its the pointer being cast, not the object. That Rock is still
a Rock regardless of which type cast you apply on the ptr. I think you
are trying to bite more than you can chew here.
>
What I did *not* expect was that it would run, but it did. Why don't
I get
a run-time error when I call fly() in my Rock masquerading as a Bird?
Because its not a Rock* anymore. Unfortunately, the fly() member
function is not accessing the object in any way, which would generate
an error.
Classic example:

#include <iostream>

class Rock
{
double d;
public:
Rock( double d_ ) : d( d_ )
{ }
double get
() const
{
return d;
}
void foo()
{
std::cout << "Rock::foo( )";
}
};

int main()
{
Rock * p;
p->foo(); // no error
p->get(); // seg fault
}

Why, cause there is no Rock object to access. All you have is an
unitialized pointer.
>
I tried it with gcc 3.4.2 (MingW Windows port) and 4.1.1
(http://oss.netfarm.it/mplayer-win32.php) and it worked in both cases.
I am on Windows XP SP2.

May 13 '07 #3
On May 13, 1:47 pm, Gavin Deane <deane_ga...@ho tmail.comwrote:
>
... Now, in your
code, the Bird* this pointer inside fly() actually points to a Rock
and so any attempt to use or dereference the pointer isn't going to
work. But none of the code in your fly() function actually uses the
this pointer - no other member functions of Bird are called and no
member data is touched. Try changing the definition of Bird as below
and you might see something more obviously strange. Watch out for
nasal demons.
<cut>

I see. I now get:
Flying at 2009312941 wing beats per minute

I was still expecting something more dramatic than that, but it will
do. Thanks.

May 13 '07 #4
On May 13, 2:12 pm, Salt_Peter <pj_h...@yahoo. comwrote:
>
You aren't converting a Rock to a bird, you are 'reinterpreting ' a
Rock* to a void* and that to a Bird*.
Converting a pointer converts the pointer, not its pointee.
I understand. My language was imprecise.
Did you not read the warnings about using reinterpret_cas t?
Most certainly.
>
Again, its the pointer being cast, not the object. That Rock is still
a Rock regardless of which type cast you apply on the ptr.
I may be a newbie, but I am not *that* new. I would like to take this
opportunity to remind you of my post's subject line, which is:
*BOGUS CAST ... WORKS - WHY?* I know that my Rock is still
a Rock. I just wanted to know why my Rock did not sink like a
stone, as a proper Rock should have.

I think you
are trying to bite more than you can chew here.
I am doing nothing of the kind. I am doing an exercise from a
textbook, the entire point of which is to show:

1) what can happen when you perform bogus casts, and
2) that C allows assignments to and/or from void *
without a cast, while C++ does not.

If you had bothered to read my post, you would have seen that.
Then again, you didn't even read the subject line. No matter
how anxious you are to attack hapless newbies, you should
at least read the post first.
>
What I did *not* expect was that it would run, but it did. Why don't
I get
a run-time error when I call fly() in my Rock masquerading as a Bird?

Because its not a Rock* anymore. Unfortunately, the fly() member
function is not accessing the object in any way, which would generate
an error.
Which is the useful answer to my query.Thank you.
Classic example:
<Classic example cut>
It crashes at run-time. Now that's more like it.

May 13 '07 #5
On May 14, 6:15 am, johnbrown...@ho tmail.com wrote:
What I did *not* expect was that it would run, but it did. Why don't
I get a run-time error when I call fly() in my Rock masquerading as a Bird?
Your expectation is wrong. When you write code that
is compilable but has bogus effects, anything could
happen. Maybe you will get a runtime error but maybe
not. Often it *appears* to work normally, as in your
example, but then fails just when you have to do a
demonstration of your code.

May 13 '07 #6

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

Similar topics

4
3732
by: Clint Hill | last post by:
I am working on a project that I would like to have some extensibility for later. So with this I am using interfaces to pass objects to derived classes. However I am running into a situation where two seperate classes won't cast each other even though they implement the same interface. The classes are identical yet won't convert. Here is...
6
6009
by: Jordi Vilar | last post by:
Hi All, Is there a way to dynamic_cast a pointer to a type defined by a type_info*? something like: type_info *info_of_type_to_cast = typeid(type_to_cast); type_to_cast *casted = really_dynamic_cast<info_of_type_to_cast>(my_data_ptr);
2
11514
by: Abhijit Bhadra | last post by:
Hi , I was trying to build my project in VC with latest Service Packs but got this error . C:\Program Files\Microsoft Visual Studio\VC98\ATL\INCLUDE\atlconv.h(125) : error C2440: 'return' : cannot convert from 'const char *' to 'const unsigned short *' Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or...
7
24825
by: VPaul | last post by:
I hope I am posting to the correct group for assistance. Please advise me if there is another group I should go to. I am new to this, so I apologize if I don't explain this very well. I do need some help. Thanks in advance. I am trying to bring data in to a Visual Foxpro application from an AS/400. I have the Client Access ODBC driver...
5
1559
by: Jon | last post by:
I am constantly getting reports in my task list like these: * 'someObjectName" is not a member of 'someOtherObjectName' * Handles clause requires a WithEvents variable. * Name 'someName' is not declared These errors are totally erroneous. If I go into the class and cut the offending code and repaste it in the same spot the errors...
8
4031
by: Asfand Yar Qazi | last post by:
Hi, I have the following header file in my 'everything useful I think of in one place' library: ============= BEGIN CODE SNIPPET =========== /** All classes that derive from this obtain a 'virtual constructor' - ie if the 'clone()' method is called on a polymorphic type, an object of the same (unknown) type is returned. */
18
3097
by: mark | last post by:
class SORef {...}; class SelectedFORef : public SORef {...}; SOFORef SOCastToSOF(SORef sor) { SelectedFORef sof=nil; sof=dynamic_cast<SelectedFORef>(sor); return sof; };
14
4413
by: andreyvul | last post by:
g++ says a reinterpret cast from void* is disallowed; however, all I'm trying to do is de-capsulate a void* argument that holds the pointer to a class (and static_cast forces cast constructor) any solutions? also this pops up: 43: error: expected unqualified-id before 'return' code: includes: stdio.h, stdlib.h, time.h, pthread.h struct:...
7
1462
by: Icario | last post by:
I have an error when i compile this: class A { public: void f(A&) {} }; class B: public A { public: void f(B&) {}
0
7695
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...
0
7922
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. ...
0
8119
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...
0
7964
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...
1
5509
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...
0
3653
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...
0
3637
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2111
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
1
1209
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.