473,779 Members | 1,921 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

I don't get it

Jo
class A {

public:

char text_a[100];

A() { *text_a=0; }
~A() {}
};
//-----------------------------------------------------------------------------
class B {

public:

char text_b[100];

B() { *text_b=0; }
~B() {}
};
//-----------------------------------------------------------------------------
class C : public A, public B {

public:

char text_c[100];

C() { *text_c=0; }
~C() {}
};
//-------------------------------------------------------------------------------
void test() {

B *bp1,*bp2;
C c,*cp1,*cp2,*cp 3;
void *p;

strcpy(c.text_a ,"hello a");
strcpy(c.text_b ,"hello b");
strcpy(c.text_c ,"hello c");
cp1=&c;
p=cp1;
bp1=cp1; // ok
bp2=(B*)p; // resulting bp2 is WRONG!
cp2=(C*)p; // ok
cp3=(C*)bp2; // resulting cp3 is WRONG! Which is logical because bp2
is already wrong.
}
//-----------------------------------------------------------------------------

So the hot spot is the bp2=(B*)p;

What's wrong with that???

I can imagine someone saying "p is not pointing to a B object".
But if you think about it, conceptually, it does, imho.

So is it more a technical matter of compiling this!?

Maybe i'm stupid and/or missing something essential about C++.

If so, please give me a link to where i can study this right.

Cheers,

Jo

Jun 18 '07
31 1928
On Jun 19, 7:20 am, Jo <jo.lan...@tele net.bewrote:
If C is derived from A & B, then a C object IS an A and IS a B. At the
same time.
Yes, but an A is not a B. The two are unrelated
except in that they are both part of a C. If
you are pointing to an A, then the only way you
are going to be able to point to a related B is
if you know you are actually pointing to an A
sub-object of a C. Which is why this doesn't work
if you are using a pointer to void, which contains
no type information.
// quick recap: class C is derived from both class A and B

A *ap;
B *bp;
C c,*cp;

cp=&c;
ap=cp;
bp=(B*)ap;
This is a reinterpret-cast, because A and B are unrelated
types (see above). The pointer 'ap' has lost the information
that it is actually pointing to an A that's a subobject
of a C.
or the last line being

bp=static_cast< B*>(ap);
Should be a compliation error for the above reason.

You can perform the conversion successfully:
bp = dynamic_cast<B *>(ap);

which tells the compiler to find the biggest object
that *ap is a sub-object of, and then try to find a
B object within that object. This is sometimes
called cross-casting.

Note, I'm not entirely sure about this, but I think
this only works if A and B are both polymorphic
classes, that is, they both contain at least one
virtual function (which will usually be the virtual
destructor). You might just get a null pointer if
this requirement is not met.

Jun 18 '07 #21
Jo
Old Wolf wrote:
>On Jun 19, 7:20 am, Jo <jo.lan...@tele net.bewrote:

>>If C is derived from A & B, then a C object IS an A and IS a B. At the
same time.


Yes, but an A is not a B. The two are unrelated
except in that they are both part of a C. If
you are pointing to an A, then the only way you
are going to be able to point to a related B is
if you know you are actually pointing to an A
sub-object of a C. Which is why this doesn't work
if you are using a pointer to void, which contains
no type information.
>>// quick recap: class C is derived from both class A and B

A *ap;
B *bp;
C c,*cp;

cp=&c;
ap=cp;
bp=(B*)ap;


This is a reinterpret-cast, because A and B are unrelated
types (see above). The pointer 'ap' has lost the information
that it is actually pointing to an A that's a subobject
of a C.
>>or the last line being

bp=static_cas t<B*>(ap);


Should be a compliation error for the above reason.

You can perform the conversion successfully:
bp = dynamic_cast<B *>(ap);

which tells the compiler to find the biggest object
that *ap is a sub-object of, and then try to find a
B object within that object. This is sometimes
called cross-casting.
That's powerful!

But at what cost?

Do you know how heavy the RTTI overhead is

-on memory
-on cpu

?

If it's similar to using virtual functions, then it's ok.
>Note, I'm not entirely sure about this, but I think
this only works if A and B are both polymorphic
classes, that is, they both contain at least one
virtual function (which will usually be the virtual
destructor). You might just get a null pointer if
this requirement is not met.

Jun 18 '07 #22
Jo <jo@mutools.com wrote in
news:PI******** *************@p hobos.telenet-ops.be:
>
Andre Kostur wrote:
>>Jo <jo*******@tele net.bewrote in
news:fa****** *************** @phobos.telenet-ops.be:
[more snip as the issue has been resolved]
>>

No "getclassid " function required.

Indeed.

But i prefer not to use RTTI for the reasons mentioned in the earlier
post.
Next item.... measure, measure, measure. How do you know that your own
RTTI method is ligher-weight than the one that the compiler is using?
>>However, note that there's no mention
of B anywhere in there (other than the inheritance)... . so how does B
get involved in this question?

I guess i was confused:

Because i ran into the casting problem (due to the use of the void*),
i started thinking that it had to do with the multiple inheritance...

I really didn't know that using a void* abandons all the class
relation info. (and that after all these years of programming, damn
damn damn)

Thanks a lot for your help!

A dummy got a bit less dummy :)
Ask questions... that's what we're here for :)
Jun 18 '07 #23
Jo
Andre Kostur wrote:
>Jo <jo@mutools.com wrote in
news:PI******* **************@ phobos.telenet-ops.be:

>>Andre Kostur wrote:
>>>Jo <jo*******@tele net.bewrote in
news:fa***** *************** *@phobos.telene t-ops.be:


[more snip as the issue has been resolved]
>>>No "getclassid " function required.
Indeed.

But i prefer not to use RTTI for the reasons mentioned in the earlier
post.


Next item.... measure, measure, measure. How do you know that your own
RTTI method is ligher-weight than the one that the compiler is using?
True.

That's also why i asked about the cost of RTTI.

At the moment i don't have a clue.
>>>However, note that there's no mention
of B anywhere in there (other than the inheritance)... . so how does B
get involved in this question?
I guess i was confused:

Because i ran into the casting problem (due to the use of the void*),
i started thinking that it had to do with the multiple inheritance...

I really didn't know that using a void* abandons all the class
relation info. (and that after all these years of programming, damn
damn damn)

Thanks a lot for your help!

A dummy got a bit less dummy :)


Ask questions... that's what we're here for :)

Jun 18 '07 #24
Jo
Jo wrote:
Andre Kostur wrote:
>Jo <jo@mutools.com wrote in
>>But i prefer not to use RTTI for the reasons mentioned in the earlier
post.


Next item.... measure, measure, measure. How do you know that your
own RTTI method is ligher-weight than the one that the compiler is
using?


True.

That's also why i asked about the cost of RTTI.

At the moment i don't have a clue.

Well, i've been experimenting a bit with dynamic_cast and must say it's
a nice feature.

Why is it that i read al these warnings about RTTI, not only about the
overhead, but also about "it's better not to use it".

Didn't find some explicit reasoning yet.

Jun 18 '07 #25
Jo
Jo wrote:
Jo wrote:
>Andre Kostur wrote:
>>Jo <jo@mutools.com wrote in

But i prefer not to use RTTI for the reasons mentioned in the earlier
post.

Next item.... measure, measure, measure. How do you know that your
own RTTI method is ligher-weight than the one that the compiler is
using?

True.

That's also why i asked about the cost of RTTI.

At the moment i don't have a clue.

Well, i've been experimenting a bit with dynamic_cast and must say
it's a nice feature.

Why is it that i read al these warnings about RTTI, not only about the
overhead, but also about "it's better not to use it".

I'm sorry, must be more precise: the warnings i read is more like
"better not to use it, unless really necessary".
>
Didn't find some explicit reasoning yet.
Jun 18 '07 #26
Jo <jo@mutools.com wrote in
news:6G******** *************@p hobos.telenet-ops.be:
Jo wrote:
>Jo wrote:
>>Andre Kostur wrote:

Jo <jo@mutools.com wrote in

But i prefer not to use RTTI for the reasons mentioned in the
earlier post.

Next item.... measure, measure, measure. How do you know that your
own RTTI method is ligher-weight than the one that the compiler is
using?

True.

That's also why i asked about the cost of RTTI.

At the moment i don't have a clue.

Well, i've been experimenting a bit with dynamic_cast and must say
it's a nice feature.

Why is it that i read al these warnings about RTTI, not only about
the overhead, but also about "it's better not to use it".


I'm sorry, must be more precise: the warnings i read is more like
"better not to use it, unless really necessary".
Performance-wise there is a certain cost to using it, but I don't think
it would be any heavier than attempting to implement your own. I think
this is really a QoI (Quality of Implementation) issue with whatever
compiler you're using.

However, a necessity to using dynamic_cast<te nds to indicate a
potential flaw in your design. You should really be asking yourself why
you need to know the derived type. Couldn't it be better implemented as
a virtual function in the base class? So if the function you're
attempting to call in C is already virtual in A, then you don't need
explicitly know that you're working with a C object. Just call the
function through the A* and let the compiler follow the virtual dispatch
to call the real function.
Jun 18 '07 #27
On Jun 18, 6:17 pm, Jo <jo.lan...@tele net.bewrote:
class A {
public:
char text_a[100];
A() { *text_a=0; }
~A() {}};
//-----------------------------------------------------------------------------
class B {
public:
char text_b[100];
B() { *text_b=0; }
~B() {}};
//-----------------------------------------------------------------------------
class C : public A, public B {
public:
char text_c[100];
C() { *text_c=0; }
~C() {}};
//-------------------------------------------------------------------------------
void test() {
B *bp1,*bp2;
C c,*cp1,*cp2,*cp 3;
void *p;

strcpy(c.text_a ,"hello a");
strcpy(c.text_b ,"hello b");
strcpy(c.text_c ,"hello c");
cp1=&c;
p=cp1;
bp1=cp1; // ok
bp2=(B*)p; // resulting bp2 is WRONG!
And why should it be otherwise? You do something illegal,
specified as undefined behavior, and you get undefined behavior.

p is a void*. About the only things you can do with a void*
(except copying it) is cast it back to the *original* type, or
to a character type to access the underlying raw memory. Since
the original type was C*, casting it back to anything but a C*
is undefined behavior, and anything can happen.

bp2 = (B*)(C*)p ;

should work.

[...]
So the hot spot is the bp2=(B*)p;
What's wrong with that???
It's forbidden by the language.

[...]
If so, please give me a link to where i can study this right.
Not a link, but in the standard:

§4.10 Pointer conversions (paragraph 2):

An rvalue of type "pointer to cv T ," where T is an
object type, can be converted to an rvalue of type
"pointer to cv void". The result of converting a
"pointer to cv T" to a "pointer to cv void" points to
the start of the storage location where the object of
type T resides, as if the object is a most derived
object (1.8) of type T (that is, not a base class
subobject). The null pointer value is converted to the
null pointer value of the destination type.

And §5.2.9 Static cast (paragraph 11):

An rvalue of type "pointer to cv1 void" can be converted
to an rvalue of type "pointer to cv2 T", where T is an
object type and cv2 is the same sv-qualifiation as, or
greater cv-qualifiation than, cv1. The null pointer
value is converted to the null pointer value of the
destination type. A value of type pointer to object
converted to "pointer to cv void" and back, possibly
with different cv-qualifiation, shall have its original
value.

You'll note, in that last paragraph, that nothing is said
about the value when converting back to a different type;
the results are not defined by the standard, and can be
anything.

--
James Kanze (GABI Software, from CAI) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jun 19 '07 #28
Jo
Andre Kostur wrote:
>Jo <jo@mutools.com wrote in
news:6G******* **************@ phobos.telenet-ops.be:
>>Jo wrote:
>>>Jo wrote:

Andre Kostur wrote:

>Jo <jo@mutools.com wrote in
>
>
>
>>But i prefer not to use RTTI for the reasons mentioned in the
>>earlier post.
>>
>>
>
>Next item.... measure, measure, measure. How do you know that your
>own RTTI method is ligher-weight than the one that the compiler is
>using?
>
>

True.

That's also why i asked about the cost of RTTI.

At the moment i don't have a clue.

Well, i've been experimenting a bit with dynamic_cast and must say
it's a nice feature.

Why is it that i read al these warnings about RTTI, not only about
the overhead, but also about "it's better not to use it".

I'm sorry, must be more precise: the warnings i read is more like
"better not to use it, unless really necessary".


Performance-wise there is a certain cost to using it, but I don't think
it would be any heavier than attempting to implement your own. I think
this is really a QoI (Quality of Implementation) issue with whatever
compiler you're using.

However, a necessity to using dynamic_cast<te nds to indicate a
potential flaw in your design. You should really be asking yourself why
you need to know the derived type. Couldn't it be better implemented as
a virtual function in the base class? So if the function you're
attempting to call in C is already virtual in A, then you don't need
explicitly know that you're working with a C object. Just call the
function through the A* and let the compiler follow the virtual dispatch
to call the real function.
Thought 1: If every very base class should foresee all virtual functions
that are coming down the hierarchic tree (or do they say "up" the tree?
still confused), then these base classes get much too much cluttered
with non-relevant virtual funcs!

Thought 2: If class C is derived from class A and B, both having virtual
funcs, and i have an A pointer to a C object, and need to call a B func
of the C object, then do you propose to copy all the virtuals of B in A?
I'm confident the answer is no.

So these are two common situations where i need to know what kind of
object i'm dealing with.

In fact, the two thoughts can be summarized to this common reason to use
RTTI: to avoid "virtual clutter".

My conclusion: If you think about it pure conceptually, i don't see
what's wrong with using RTTI.Using virtuals to avoid RTTI is one good
strategy. Using RTTI to avoid virtuals is another good strategy. It are
two equivalent techniques, imo, one better in situation a, the other
better in situation b.

Jun 19 '07 #29
On Jun 18, 10:17 pm, Jo <j...@mutools.c omwrote:
John Harrison wrote:
[...]
dynamic_cast does do base to derived conversion, that's it's main use.
Where are you getting your information?
I got that fromhttp://www.cplusplus.c om/doc/tutorial/typecasting.htm l
But i was just reading another webpage where they indeed use
base-to-derived dynamic casts...
Did i misunderstand the cplusplus page?
You didn't read the sentence completely. It says: "The second
conversion in this piece of code would produce a compilation
error since base-to-derived conversions are not allowed with
dynamic_cast UNLESS the base class is polymorphic." Note that
final clause, with the unless. In their example, the base class
didn't have any virtual functions, so using dynamic_cast to the
derived would be a compiler error.

Generally speaking, you should avoid using void* as much as
possible, and use dynamic_cast exclusively for moving between
classes in a hierarchy. When you can't avoid void*, e.g.
because of legacy or C interfaces, always cast back to exactly
the type of pointer you originally had, then go from there.
Note that often, this means casting to a specific type before
casting to void*. For example (using pthread_create as an
example, but it could be any C API function that takes a pointer
to function and a void*):

class Thread
{
public:
virtual ~Thread() {}
virtual void* run() = 0 ;
} ;

extern "C"
void*
threadStarter( void* p )
{
Thread* t = static_cast< Thread* >( p ) ;
return t->run() ;
}

void
f()
{
// MyThread derives from Thread...
pthread_t t ;
pthread_create( &t, NULL, &threadStart er, new MyThread ) ;
}

As written, this is undefined behavior. The last code line must
be:

pthread_create(
&t, NULL, &threadStart er, static_cast< Thread* >( new
MyThread ) ) ;

(The problem is, that as it is undefined behavior, it might seem
to work some of the time anyway. On most implementations , for
example, it will seem to work as long as only single inheritance
is involved.)

Note that the solution here does NOT involve dynamic_cast; you
don't want a pointer to the most derived type, but to the type
to which the void* will ultimately be converted. (The
documentation of "threadStar ter" should specify this.)

--
James Kanze (GABI Software, from CAI) email:ja******* **@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientier ter Datenverarbeitu ng
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Jun 19 '07 #30

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

Similar topics

303
17775
by: mike420 | last post by:
In the context of LATEX, some Pythonista asked what the big successes of Lisp were. I think there were at least three *big* successes. a. orbitz.com web site uses Lisp for algorithms, etc. b. Yahoo store was originally written in Lisp. c. Emacs The issues with these will probably come up, so I might as well mention them myself (which will also make this a more balanced
16
2423
by: mike420 | last post by:
Tayss wrote: > > app = wxPySimpleApp() > frame = MainWindow(None, -1, "A window") > frame.Show(True) > app.MainLoop() > Why do you need a macro for that? Why don't you just write
12
4055
by: AFN | last post by:
I am running the code below to generate XML from a data table. But some fields in the data table are Null for every record. Suppose field5 has a null database value. I would expect to see: <field5></field5> or <field5 /> but instead it doesn't even show the field at all for those records where field5 is Null! Instead it just shows: <field4>Whatever</field4>
3
3051
by: Douglas Buchanan | last post by:
Buttons don't work if form is opened on startup A2k If 'frmMain' is set to open by default at startup none of the buttons work. If 'frmMain' is opened from the database window then all the buttons work. The form's name ('frmMain') is selected from in the Startup dialog box.
28
2505
by: DFS | last post by:
I'm unfortunately about to change, or sever, a two-year relationship with a very slow-paying client. Most of the 15 invoices I've sent them arrive 6 to 8 weeks late, and usually only after repeated calls to the requesting client department, AP and finally Legal. I really think they would never pay some of these invoices if I didn't hound them. I don't have the time or energy or stress-handling to make repeated collection calls and...
0
17817
by: Nashat Wanly | last post by:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnaskdr/html/askgui06032003.asp Don't Lock Type Objects! Why Lock(typeof(ClassName)) or SyncLock GetType(ClassName) Is Bad Rico Mariani, performance architect for the Microsoft® .NET runtime and longtime Microsoft developer, mentioned to Dr. GUI in an e-mail conversation recently that a fairly common practice (and one that's, unfortunately, described in some of our...
19
3882
by: LP | last post by:
I am using (trying to) CR version XI, cascading parameters feature works it asks user to enter params. But if page is resubmitted. It prompts for params again. I did set ReuseParameterValuesOnRefresh="True" in a viewer, but it still doesn't work. Did anyone run into this problem. What's the solution? Please help. Thank you
10
2099
by: Frank | last post by:
I've done this a few times. In a solution I have a project, Say P1, and need another project that will contain much code that is similar to that of P1. I hope no one gets hung up on why I don't somehow share the code. So, I copy the folder P1 is in, change the new folder name, and is VS2005 to change all occurrences of P1's name tp P2's name.
21
2068
by: jehugaleahsa | last post by:
Hello: I had an hour-long discussion with my boss today. Last night, right before I dozed off, I realized some of his code resulted in duplicate processing. I tried to explain it to him and he kept saying, "I'm afraid to say it's 'OK' to change it because everything I did was for a reason." Well, I know better. My boss' old code is written in some cryptic C file with Oracle precompiler macros barfed all over it. Once I figured out how...
1
11303
Nepomuk
by: Nepomuk | last post by:
You might have heard about Linux, but you don't know what it is? Or you know a few things about it, but they terrify you? Well, then this article is for you. Don't be afraid - Everyone can use Linux! Part 1: What is Linux and why should I use it? Linux is an Operating System (short: OS). OK, so what is an OS? Let me explain: Nearly everybody knows Windows. But what exactly does it actually do? Windows is an example for a OS and one of it's...
0
9471
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
10136
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
8958
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
7478
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
5372
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
5501
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4036
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
3631
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2867
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.