Class offset with its Base in Multiple inheritance

Started by
22 comments, last by monamimani 12 years, 6 months ago
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
Advertisement
MultipleInheritance::dummy is placed after all the inherited data. That's why you can have Parent1 at offset 0.

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.


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

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.
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.

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....
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.

[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.

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.

This topic is closed to new replies.

Advertisement