Is there any way to know the size of derived class using base class pointer?

Started by
9 comments, last by SiCrane 13 years, 6 months ago
There are multiple inheritance objects like below

class CBase {};class CDerived1 : public CBase{  int a, b;};class CDerived2 : public CDerived1 {  int c, d;};


and i have a list of CBase* pointers (these are pointing CDerived1, CDerived2)

now, Is there any way to know the size of the derived class just using CBase* pointer?

* I don't want to make another variable in base class
* I don't want to make any virtual function and add it in every derived classes


So I've tried like this

class CBase {};template <typename T>class CBase2 {  size_t GetSize() { return sizeof(T); }}class CDerived1 : public CBase2<CDerived1>{}


It works good in both way (i can have list of CBase* pointers and satisfying 2 conditions above) but this has problem when CDerived2 inherites from CDerived1.

so i'm asking for a great advise and please let me know any kind of way to do that. thank you.
Advertisement
Nope, C++ lacks the reflective metadata to enable this. However, in C++ the size of an object isn't usually important, can you tell us why you think you need it?
If I had to deal with it I would create class variable not using a pointer and then I would use sizeof() function:

CDerived c;
cout<<sizeof(c);

It would tell me how much space requires that class. I assume that You know the range of possible classes to be used as class type T, so You could save sizes of each class in array. And you only have to find out which class do You use. You can handle that with dynamic_cast or static_cast (check google) operators.
You don't need to create an instance to do that, sizeof(CDerived) would suffice.

Really, there is no way to do this that is simpler than sizeof(CDerived) -- and I would assume that the original question comes about because the OP needs the size, perhaps for serialization, of a class that not declared when the code in question is being compiled (i.e., code in an client library subclasses CBase or some such), but the OPs code needs the size for serialization or something. In this case the interface being implemented, or a related interface, simply needs to require the implementor to provide the size somehow.

I am interested why comdown does not want to use dynamic dispatch, because this scenario is exactly what that mechanism is useful for.
There's no way to do this in the general case with standard C++. There are, however, non-standard mechanisms that can be used to achieve this, given particular implementations and/or simplifying assumptions. For example, some C++ implementations embed size information in the vtable, and you can use various hacks to read that. If you can guarantee that every object will be allocated with new and there is no multiple inheritance used, you may be able to use _msize() or some equivalent on the pointers. In some implementations it's possible to embed your own data into the vtable, including size information.
Quote:Original post by SiCrane
In some implementations it's possible to embed your own data into the vtable, including size information.
You can also override new/delete to allocate an extra few bytes, and store the size before the object. I am not sure how standards-compliant it is, but I used this hack at some point in the past to store metadata for a debug memory manager.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

That would likely break under situations using multiple inheritance, so you might as well use _msize() or it's equivalent if they are available and provide byte precision (ex: recent versions of MSVC).
Quote:Original post by no such user
That would likely break under situations using multiple inheritance, so you might as well use _msize() or it's equivalent if they are available and provide byte precision (ex: recent versions of MSVC).
Why would multiple inheritance change anything? I am talking about overriding the global new operator, *not* instance new.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

Because then a pointer to the Base type may not be directly after the size entry you stuck in the allocation.
Quote:Original post by no such user
Because then a pointer to the Base type may not be directly after the size entry you stuck in the allocation.
Mhm. Fair enough - it looks like we used an alignment trick to find the beginning of the allocation in this case.

I believe that a dynamic_cast<void *> would do the trick as well, as a cast to void * should always yield the beginning of the vtable.

Tristam MacDonald. Ex-BigTech Software Engineer. Future farmer. [https://trist.am]

This topic is closed to new replies.

Advertisement