Jump to content
  • Advertisement
Sign in to follow this  
monamimani

Class offset with its Base in Multiple inheritance

This topic is 2504 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

Hi all,

I am trying to compute the memory offset of a base class with its parents in a multiple inheritance scenario, I hope to find a general solution the would work for simple and multiple inheritance with or with out virtual function or virtual inheritance.

This is my function to compute the class offset.


template<typename ClassType, typename ParentType>
ptrdiff_t GetClassOffset()
{
static_assert(std::is_base_of<ParentType, ClassType>::value, "The parent type is not the base type of the class type.");

constexpr size_t max_size = sizeof(ClassType) + sizeof(ParentType);
const ClassType* classType = reinterpret_cast<const ClassType* >(max_size);
const ParentType* baseType = static_cast<const ParentType* >(classType);

uintptr_t classTypeOffset = reinterpret_cast<uintptr_t>(classType);

uintptr_t baseTypeOffset = reinterpret_cast<uintptr_t>(baseType);

return classTypeOffset - baseTypeOffset;
}




And I am testing with those classes



/// First Parent
class Parent1
{
int dummy;
};
/// Second Parent
class Parent2
{
int dummy;
};

/// Third Parent
class Parent3
{
int dummy;
};

/// Fourth Parent
class Parent4
{
int dummy;
};

/// Fifth Parent
class Parent5
{
int dummy;
};

class MultipleInheritance: public Parent1, public Parent2, public Parent3, public Parent4, public Parent5
{
int dummy;
};





I then tested with this code


std::cout << "Class offset of MultipleInheritance class with " << std::endl;
std::cout<< "MultipleInheritance: " << GetClassOffset< MultipleInheritance, MultipleInheritance>() << std::endl;
std::cout<< "Parent1: " << GetClassOffset< MultipleInheritance, Parent1>() << std::endl;
std::cout<< "Parent2: " << GetClassOffset< MultipleInheritance, Parent2>() << std::endl;
std::cout<< "Parent3: " << GetClassOffset< MultipleInheritance, Parent3>() << std::endl;
std::cout<< "Parent4: " << GetClassOffset< MultipleInheritance, Parent4>() << std::endl;
std::cout<< "Parent5: " << GetClassOffset< MultipleInheritance, Parent5>() << std::endl;


And the result was:


Class offset of MultipleInheritance class with
MultipleInheritance: 0
Parent1: 0
Parent2: -4
Parent3: -8
Parent4: -12
Parent5: -16


What i don't understand is why the offset of the class MultipleInheritance with Parent1 is 0 shouldn't it be -4? and thus everything else would be offseted by 4? Maby the problem is with the function getClassOffset but I don't see it.

Also is this function can cover all the scenario possible, I think it is possible but maybe i don't see it.

Anybody can help me?

Thanks alot

Share this post


Link to post
Share on other sites
Advertisement
MultipleInheritance::dummy is placed after all the inherited data. That's why you can have Parent1 at offset 0.

Share this post


Link to post
Share on other sites

I am trying to compute the memory offset of a base class with its parents in a multiple inheritance scenario, I hope to find a general solution the would work for simple and multiple inheritance with or with out virtual function or virtual inheritance.
[/quote]

I'm fairly certain that there's no portable, reproducible way to do this for all scenarios. I'm curious about what problem you're trying to solve.

Share this post


Link to post
Share on other sites


I am trying to compute the memory offset of a base class with its parents in a multiple inheritance scenario, I hope to find a general solution the would work for simple and multiple inheritance with or with out virtual function or virtual inheritance.


I'm fairly certain that there's no portable, reproducible way to do this for all scenarios. I'm curious about what problem you're trying to solve.
[/quote]

The problem i am trying to solve is a reflection system. I need the offset to make my own dynamic_cast. Really there is no portable way? Why?

thanks

Share this post


Link to post
Share on other sites

MultipleInheritance::dummy is placed after all the inherited data. That's why you can have Parent1 at offset 0.


Really? What am i missing, in those 2 static_cast:


const ClassType* classType = reinterpret_cast<const ClassType* >(max_size);
const ParentType* baseType = static_cast<const ParentType* >(classType[font="monospace"][/font][color=#666600][font=CourierNew, monospace][size=2]);[/font]



They both return the same address in both cases of GetClassOffset(), for Parent1 and MultipleInheritance. but I am pretty sure that if I do:


int dummyOfClass = classType->dummy;
int dummyOfBase = baseType->dummy;


I wont get the same dummy variable. So I must not think of something.

thanks for you answer!

What I didn't understand is why the offset with Parent1 is 0 aswell as the offset with itself. Edited by monamimani

Share this post


Link to post
Share on other sites
You are right they are two different variables. What I meant was that MultipleInheritance and Parent1 can have the same address because the Parent1 data is located at the start of MultipleInheritance. If you print the address of the dummy variables in MultipleInheritance you will see that they are ordered as Parent1::dummy, Parent2::dummy, Parent3::dummy, Parent4::dummy, Parent5::dummy, MultipleInheritance::dummy in memory.

Share this post


Link to post
Share on other sites

You are right they are two different variables. What I meant was that MultipleInheritance and Parent1 can have the same address because the Parent1 data is located at the start of MultipleInheritance. If you print the address of the dummy variables in MultipleInheritance you will see that they are ordered as Parent1::dummy, Parent2::dummy, Parent3::dummy, Parent4::dummy, Parent5::dummy, MultipleInheritance::dummy in memory.


So that mean that MultipleInheritance contain all it's parent. Ok I understand that.

I guess the way I compute the offset is wrong since it give me a negative number, i should do baseTypeOffset - classTypeOffset instead of classTypeOffset - baseTypeOffset?

This way if i want to cast from MultipleInheritance* to Parent2* I add the offset (4) and reinterpret_cast the resulting address? This would mean that a cast to Parent1 and MultipleInheritance would result to the same address and no offset?

sorry, I have a hard time to believe it, even thought it most be true....

Share this post


Link to post
Share on other sites
All this pointer casting is a bit over my head, I don't even understand why you need max_size but using a null pointer doesn't work. hmm.

What's wrong with the built in dynamic_cast? I can't see what you will be able to do with this.

Share this post


Link to post
Share on other sites

[quote name='Telastyn' timestamp='1315783317' post='4860477']

I am trying to compute the memory offset of a base class with its parents in a multiple inheritance scenario, I hope to find a general solution the would work for simple and multiple inheritance with or with out virtual function or virtual inheritance.


I'm fairly certain that there's no portable, reproducible way to do this for all scenarios. I'm curious about what problem you're trying to solve.
[/quote]

The problem i am trying to solve is a reflection system. I need the offset to make my own dynamic_cast. Really there is no portable way? Why?

thanks
[/quote]

Because I thought that memory arrangement in that scenario is compiler/system dependent. A quick search can't confirm or deny that.

Share this post


Link to post
Share on other sites

All this pointer casting is a bit over my head, I don't even understand why you need max_size but using a null pointer doesn't work. hmm.

What's wrong with the built in dynamic_cast? I can't see what you will be able to do with this.


I don't think I need max_size, I saw that on a post on this forum. I saw befor using -1 instead of max_size I think the value is not important put the type of max_siaze should be enough to represent a type.

dynamic_cast rely on RTTI to be enabled, and I don't want to enable it because it is not complet for my need. Like exposing member of a class to a editor for a data driven engin.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!