Re: [OT] C++ question re. dyn. mem.
>>>>> "MJM" == MJM <linux-support@earthlink.net> writes:
MJM> They do. My app would be broken from the start if I could not rely
MJM> on this capability. This style of type conversion is covered in
MJM> elementary C++ books by Bjarne. It's not unusual. You must be
MJM> aware of what you are doing when you do a type conversion.
MJM> Portability is a concern. I am limiting my app to Intel 32 bit
MJM> Linux. Screw everything else.
That you do not treasure portability across CPUs and compilers do not mean
others don't.
MJM> By whom? Your example is nowhere to be found in my C++ books by
MJM> Bjarne. So you are saying that Bjarne promotes bad style in his
MJM> books? Why not tell him:
MJM> http://www.research.att.com/~bs/homepage.html
You must be reading pre-standard C++ books. Bjarne's "The C++ Programming
Language, 3rd Edition" clearly stated that the () "C-style" casting syntax
should be avoided:
This C-style cast is far more dangerous than the named conversion
operators because the notation is harder to spot in a large program and
the kind of conversion intended by the programmer is not
explicit. [Section 6.2.7.]
In his "The Design and Evolution of C++", Bjarne explained that he even
wanted to strike the C-style cast out of the C++ standard except that all C
programs would become not compilable.
MJM> Besides, reinterpret_cast is probably a template function doing
MJM> this:
MJM> return ((T) x); // type conversion using cast
Definitely not. The objection of (T)x is not just its syntax, but also its
unclear behaviour. Consider the following:
#include <iostream>
using namespace std;
class B {
public:
virtual ~B() {}
};
class B1 {
public:
virtual ~B1() {}
};
class B2 {
public:
virtual ~B2() {}
};
class D: public B1, public B2 {};
int main() {
D d;
B *pb;
B2 *pb1;
pb1 = (B2 *)&d;
cout << pb1 << endl;
pb1 = reinterpret_cast<B2 *>(&d);
cout << pb1 << endl;
pb1 = static_cast<B2 *>(&d);
cout << pb1 << endl;
pb = (B *)&d;
cout << pb << endl;
}
When executed from my computer (Debian sid, gcc 3.3), it gives:
0xbffffb04 # C-style cast to B2*
0xbffffb00 # reinterpret_cast to B2*
0xbffffb04 # static_cast to B2*
0xbffffb00 # C-style cast to B*
In other words, the behaviour of a C-style cast depends on whether the
casting of the pointer is an "up-cast"/"down-cast" or not; if it is (in this
case up from D to B2) then the cast will be a static cast, doing pointer
adjustment (so that the sub-object of type B2 is found within the object of
type D); and if it is not then the cast will be a reinterpret cast, doing no
pointer adjustment. It is generally agreed that such "compiler
intelligence" is in general no good, since the programmer probably only
expect one of the two possibility will happen, and the result is sometimes
what the programmer expects and sometimes not. If the programmer expects a
static cast he should write static_cast<B2 *>(&d) so that the compiler will
emit an error if the classes are actually of two different hierarchy. If
the programmer expects a dynamic cast he should write dynamic_cast<B *>(&d)
so that you understand you are doing something that the compiler has no
control of, and dereferencing the result will probably be a programming
error.
Regards,
Isaac.
Reply to: