6

Consider the following program

 #include<iostream>
 using namespace std;
 class ClassA
{
public:
    virtual ~ClassA(){};
    virtual void FunctionA(){};

};

class ClassB
{
 public:
    virtual void FunctionB(){};
};



class ClassC : public ClassA,public ClassB
{

};

void main()
{
    ClassC aObject;
    ClassA* pA = &aObject;
    ClassB* pB = &aObject;
    ClassC* pC = &aObject;

    cout<<"pA = "<<pA<<endl;
    cout<<"pB = "<<pB<<endl;
    cout<<"pC = "<<pC<<endl;

}

pA,pB,pC are supposed to equal,but the result is

pA = 0031FD90

pB = 0031FD94

pC = 0031FD90

why pB = pA + 4? and when i change

class ClassA
{
public:
    virtual ~ClassA(){};
    virtual void FunctionA(){};

};
class ClassB
{
 public:
    virtual void FunctionB(){};
};

to

class ClassA
{
};

class ClassB
{
};

the result is

pA = 0030FAA3

pB = 0030FAA4

pC = 0030FAA3

pB = pA + 1?

denzel_wu
  • 63
  • 2
  • i think this will help you, http://stackoverflow.com/questions/254673/multiple-inheritance-from-two-derived-classes – shankar Oct 17 '13 at 03:35

3 Answers3

1

The multiply inherited object has two merged sub-objects. I would guess the compiler is pointing one of the pointers to an internal object.

Steve Wellens
  • 20,506
  • 2
  • 28
  • 69
0

C has two inherited subobjects, therefore is the concatenation of a A object and a B object. When you have an object C, it is composed of an object A followed by an object B. They're not located at the same address, that's why. All three pointers point to the same object, but as different superclasses. The compiler makes the shift for you, so you don't have to worry about that.

Now. Why is there a difference of 4 in one case and 1 in another? Well, in the first case, you have virtual functions for both A and B, therefore each subobject has to have a pointer to its vtable (the table containing the addresses of the resolved virtual function calls). So in this case, sizeof(A) is 4. In the second case, you have no virtual functions, so no vtable. But each subobject must be addressable independently, so the compiler still has to allocate for a different addresses for subobject of class A and subobject of class B. The minimum of difference between two addresses is 1. But I wonder if EBO (empty base-class optimization) should not have kicked in in this case.

Laurent LA RIZZA
  • 2,905
  • 1
  • 23
  • 41
0

That's the implementation detail of compiler. The reason you hit this case is because you have MI in your code.

Think about how the computer access the member in ClassB, it using the offset to access the member. So let's say you have two int in class B, it using following statement to access the second int member.

  *((int*)pb + 1) // this actually will be assembly generate by compiler

But if the pb point to the start of the aObject in your class, this will not work anymore, so the compiler need to generate multiple assembly version to access the same member base on the class inherit structure, and have run-time cost.

That's why the compiler adjust the pb not equal as pa, which will make the above code works, it is the most simply and effect way to implement.

And that's also explain why pa == pc but not equals with pb.

ZijingWu
  • 3,350
  • 3
  • 25
  • 40