I was just curious to know how are calls like say dynamic_cast
implemented. Is it really expensive to get the exact type of an object
being pointed to by the baseclass pointer?
The reason I am asking is because of the well known issue of pointer
arithmetic not going well with polymorphism. Consider a function like
void myFunc( baseC ptr[], int length) {
for (int i=0; i<length; i++)
ptr[i].someField = somevalue;
}
Here baseC is some base class. Now, this function will not work as
intended if I pass in an array of derived class objects. (because
ptr[i] gets mapped to (ptr + i*sizeof(baseC)) )
Is it really expensive for the Compiler to generate proper code here
rather than just the sizeof addition? By proper code, I mean get the
type info for the actual objects pointed at by ptr and use that size.
If it indeed is that expensive, can it just do it for cases like above
where I can specifically give some kind of hint that myFunc can
"possibly" be invoked with an array of derived class objects.
Thanks,
Vikram 9 1801
Vikram wrote: I was just curious to know how are calls like say dynamic_cast implemented. Is it really expensive to get the exact type of an object being pointed to by the baseclass pointer?
The reason I am asking is because of the well known issue of pointer arithmetic not going well with polymorphism. Consider a function like
void myFunc( baseC ptr[], int length) { for (int i=0; i<length; i++) ptr[i].someField = somevalue; }
Here baseC is some base class. Now, this function will not work as intended if I pass in an array of derived class objects. (because ptr[i] gets mapped to (ptr + i*sizeof(baseC)) )
Is it really expensive for the Compiler to generate proper code here rather than just the sizeof addition? By proper code, I mean get the type info for the actual objects pointed at by ptr and use that size. If it indeed is that expensive, can it just do it for cases like above where I can specifically give some kind of hint that myFunc can "possibly" be invoked with an array of derived class objects.
Thanks, Vikram
Oops! I think I already realized one of the reasons compilers dont even
try this. Like derived classes can be defined in different files so no
way a compiler would know about them when it is looking at this current
file.
Anyway, please let me know how expensive is getting run-time type info
in general. Dynamic_cast in particular
> Anyway, please let me know how expensive is getting run-time type info in general. Dynamic_cast in particular
Generally how exactly expensive RTTI is an issue of quality of
implementation. RTTI is almost certainly built on top of the virtual
function mechanism. It can be implemented as an anonymous virtual
function that traces down the inheritance graph. So you can assume O(n)+
complexity for n level of inheritance [Correct me if I am so wrong here.]
There is a polymorphic_downcast<> function template from boost cast
library you can use. It acts like dynamic cast for debug builds, and
like static_cast for release builds. Nevertheless, use it with great
caution.
Regards,
Ben
benben wrote: Anyway, please let me know how expensive is getting run-time type info in general. Dynamic_cast in particular
Generally how exactly expensive RTTI is an issue of quality of implementation. RTTI is almost certainly built on top of the virtual function mechanism. It can be implemented as an anonymous virtual function that traces down the inheritance graph. So you can assume O(n)+ complexity for n level of inheritance [Correct me if I am so wrong here.]
There is a polymorphic_downcast<> function template from boost cast library you can use. It acts like dynamic cast for debug builds, and like static_cast for release builds. Nevertheless, use it with great caution.
Regards, Ben
Thanks Ben. As of now, instead of dynamic_cast, we have just put
virtual int getSize() { return sizeof(*this);}
in all the classes of the hierarchy (some 4-5). And in myFunc, we did
ptr + i*ptr->getSize()
instead of using ptr[i]
I know this is not very elegant and especially if someone adds a new
class, he _has_ to override this method. But this is some old legacy
code and I dont want to change a lot here. And am pretty sure, there
wont be new classes added.
Thanks,
Vikram
benben wrote: Generally how exactly expensive RTTI is an issue of quality of implementation. RTTI is almost certainly built on top of the virtual function mechanism. It can be implemented as an anonymous virtual function that traces down the inheritance graph. So you can assume O(n)+ complexity for n level of inheritance [Correct me if I am so wrong here.]
I don't believe that to be the case. My understanding is that because
the vtable for each instance of a particular concrete class is the
same, and all the information necessary to construct it is available at
compile time, virtual dispatch overhead is independent of inheritance
depth -- basically it's an extra pointer deref, period (plus an
addition op for indexing? I'm not 100% sure). The only thing that has
to be done at runtime is to determine, by looking at the hidden vtable
pointer in each polymorphic class instance, which vtable to use.
Luke
Vikram schrieb: benben wrote: Anyway, please let me know how expensive is getting run-time type info in general. Dynamic_cast in particular
Generally how exactly expensive RTTI is an issue of quality of implementation. RTTI is almost certainly built on top of the virtual function mechanism. It can be implemented as an anonymous virtual function that traces down the inheritance graph. So you can assume O(n)+ complexity for n level of inheritance [Correct me if I am so wrong here.]
There is a polymorphic_downcast<> function template from boost cast library you can use. It acts like dynamic cast for debug builds, and like static_cast for release builds. Nevertheless, use it with great caution.
Regards, Ben
Thanks Ben. As of now, instead of dynamic_cast, we have just put virtual int getSize() { return sizeof(*this);} in all the classes of the hierarchy (some 4-5). And in myFunc, we did ptr + i*ptr->getSize() instead of using ptr[i]
I hope you convert ptr to (char*) before. Doing ptr[i*ptr->getSize()] is
not what you want.
Thomas
> I don't believe that to be the case. My understanding is that because the vtable for each instance of a particular concrete class is the same, and all the information necessary to construct it is available at compile time, virtual dispatch overhead is independent of inheritance depth -- basically it's an extra pointer deref, period (plus an addition op for indexing? I'm not 100% sure). The only thing that has to be done at runtime is to determine, by looking at the hidden vtable pointer in each polymorphic class instance, which vtable to use.
Luke
Ya that's true. But you are talking about virtual function, and I was
talking about dynamic_cast.
Virtual function by its own is a mere O(0) operation. I was talking
about the algorithm inside that possible virtual function that is O(n)
by its simplest.
Regards,
Ben
> Thanks Ben. As of now, instead of dynamic_cast, we have just put virtual int getSize() { return sizeof(*this);} in all the classes of the hierarchy (some 4-5). And in myFunc, we did ptr + i*ptr->getSize() instead of using ptr[i]
I know this is not very elegant and especially if someone adds a new class, he _has_ to override this method. But this is some old legacy code and I dont want to change a lot here. And am pretty sure, there wont be new classes added.
Thanks, Vikram
Wow, I didn't know you have an array to BaseC instead of an array to
BaseC*. How did you convert DerivedC[], say, to BaseC[]?
There is a design problem here: why do you have an array to BaseC (not
BaseC*) instead of an array to DerivedC?
As with the legacy code, if you 1) are so confident that the BaseC[]
array is indeed a DerivedC array, and 2)want to bypass the runtime type
checking, then why don't you just use static_cast?
void myFunc( baseC ptr[], int length) {
DerivedC* ptr2 = static_cast<DerivedC*>(&ptr[0]);
for (int i=0; i<length; i++)
ptr2[i].someField = somevalue;
}
Regards,
Ben
benben wrote: I don't believe that to be the case. My understanding is that because the vtable for each instance of a particular concrete class is the same, and all the information necessary to construct it is available at compile time, virtual dispatch overhead is independent of inheritance depth -- basically it's an extra pointer deref, period (plus an addition op for indexing? I'm not 100% sure). The only thing that has to be done at runtime is to determine, by looking at the hidden vtable pointer in each polymorphic class instance, which vtable to use.
Luke
Ya that's true. But you are talking about virtual function, and I was talking about dynamic_cast.
Virtual function by its own is a mere O(0) operation.
O(1). There are no O(0) operations. Review the formal definition
(e.g. on Wikipedia) if you are unclear as to why.
I was talking about the algorithm inside that possible virtual function that is O(n) by its simplest.
By what rationale? The O(n) exploration of the inheritance hierarchy
necessary to determine the validity of a dynamic_cast can be, and
surely is in any reasonable implementation, done at compile time. I
seriously doubt there's any reason the runtime operation can't be O(1).
Luke
benben schrieb:
>Thanks Ben. As of now, instead of dynamic_cast, we have just put virtual int getSize() { return sizeof(*this);} in all the classes of the hierarchy (some 4-5). And in myFunc, we did ptr + i*ptr->getSize() instead of using ptr[i]
I know this is not very elegant and especially if someone adds a new class, he _has_ to override this method. But this is some old legacy code and I dont want to change a lot here. And am pretty sure, there wont be new classes added. Thanks, Vikram
Wow, I didn't know you have an array to BaseC instead of an array to
BaseC*. How did you convert DerivedC[], say, to BaseC[]?
There is a design problem here: why do you have an array to BaseC (not
BaseC*) instead of an array to DerivedC?
As with the legacy code, if you 1) are so confident that the BaseC[]
array is indeed a DerivedC array, and 2)want to bypass the runtime type
checking, then why don't you just use static_cast?
void myFunc( baseC ptr[], int length) {
DerivedC* ptr2 = static_cast<DerivedC*>(&ptr[0]);
for (int i=0; i<length; i++)
ptr2[i].someField = somevalue;
}
Because he wants to use this function polymorphically with baseC[] and
DericedC[]?
Thomas This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics
by: Rick |
last post by:
Hi,
I wrote a few classes recently and am writing a small GC implementation
for C++. I will be implementing my own gc_ptr type maintain a list where
I'll store pointers to allocated memory. I...
|
by: shishir |
last post by:
Please consider the following
//file test.cpp
#include <iostream>
int main()
{
int x;
try
{
throw x;
|
by: Kleidemos |
last post by:
If I implement a simple RTTI system, more simple than C++ RTTI system
for my program and this system is plus or minus:
#define DEF_RTTI_BASE(name) virtual inline const char *Name(){ return...
|
by: Agoston Bejo |
last post by:
Hello there,
I would like to know what overheads there are to think of when using RTTI. I
understand that enabling RTTI increases the sizes of the classes, but not
the objects themselves. This...
|
by: Jim Strathmeyer |
last post by:
I'm writing code with a whole lot of inheritance and am finding myself
getting an object's type a lot. I do this by having a enumerated data
member in the base class, and setting it in the derived...
|
by: denny |
last post by:
Hey all,
I know that dynamic_cast<> takes some time, but , for instance, is there a memoy cost associated in with it? Does it have to maintain a table in memory, thus bloating the runtime ram...
|
by: Steven T. Hatton |
last post by:
I'm trying to work out a design for dynamically determining file types, and
for generating new files of a given type. I'm curious to know what others
think of my current strategy. Is it "so...
|
by: dotNeter |
last post by:
I'm studying the RTTI, and my current work is concern for how to get
the self-defined type at runtime, that's exactly what the RTTI does.
I mean, in my application, I built several self-defined...
|
by: Chameleon |
last post by:
I know than dynamic_cast check string name of derived to base class and
if one of them match, return the pointer of that object or else zero.
I suppose, I dynamic_cast instead of strings, checks...
|
by: emmanuelkatto |
last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud.
Please let me know.
Thanks!
Emmanuel
|
by: BarryA |
last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
|
by: Sonnysonu |
last post by:
This is the data of csv file
1 2 3
1 2 3
1 2 3
1 2 3
2 3
2 3
3
the lengths should be different i have to store the data by column-wise with in the specific length.
suppose the i have to...
|
by: Hystou |
last post by:
There are some requirements for setting up RAID:
1. The motherboard and BIOS support RAID configuration.
2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
|
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,...
|
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...
|
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,...
|
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...
|
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...
| |