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.
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.
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 :)
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 :)
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.
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.
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.
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
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.
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 This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
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
|
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
|
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>
|
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.
|
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...
| |
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...
|
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
|
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.
|
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...
|
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...
|
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: 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: 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...
|
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: 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...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
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.
|
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...
| |