Sign in to follow this  

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

This topic is 2634 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Quote:
Original post by swiftcoder
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.

No, dynamic_cast to void * yields a pointer to the most derived object pointed to by the object. It most certainly is not a pointer to the beginning of the vtable, unless you're dealing with a C++ implementation moronic enough to embed the entire vtable in every instance. It may, however, be a pointer to a pointer to a vtable. Or if the first base class of the object is non-polymorphic it may be a pointer to the first data member in that base.

Share this post


Link to post
Share on other sites

This topic is 2634 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this