1
struct Base1{

    int b1[100];

};

struct Base2{

    int b2;

    virtual void foo() {}

};

struct Derived : public Base1, public Base2{

    int d;

};

int main(){

    Derived D;
    Base2* p_B2 = &D;

    std::cout << &D << "\n";
    std::cout << p_B2 << "\n";

    std::cout << sizeof( D) << "\n";
    std::cout << sizeof( *p_B2) << "\n";

    std::cout << &(D.b2) << "\n";
    std::cout << &(p_B2->b2) << "\n";

    return 0;

}

If the virtual function is commented out, the output is something like:

0x7fffffffdcb0
0x7fffffffde40
408
4
0x7fffffffde40
0x7fffffffde40

If the virtual function is there, the output is:

0x7fffffffdca0
0x7fffffffdca0
416
16
0x7fffffffdca8
0x7fffffffdca8

The size difference is the v-pointer + padding, but where is the offset? Why do those point to the same address? Why is there only 8 bytes (the v-pointer I assume) difference between D and D.b2 when there should be at least 100 int-s between them?

(Also my debugger (gdb) shows p_B2 as "Derived" type.)

curiousguy
  • 8,038
  • 2
  • 40
  • 58
AdyAdy
  • 988
  • 6
  • 19
  • Did you check this [unexpected result after cast from void * to 2nd base class](https://stackoverflow.com/questions/2379427/multiple-inheritance-unexpected-result-after-cast-from-void-to-2nd-base-class) – Mohammad Kanan Mar 17 '18 at 19:00
  • @MohammadKanan Now I did check it but the OP there uses reinterpret cast which is meant to produce "wrong" results in that situation. I'm using static-cast here which considers the pointer-offset between the base and derived. – AdyAdy Mar 17 '18 at 19:07
  • First, I don't see any `static_cast`, or in fact, any kind of cast in your code. Post a working example that demonstrates the problem. Second, unless the compiler documentation specifically tells you how it will lay out the memory, then you can't make any assumptions. If you want to understand how it organizes memory, you'll have to find the compiler source code. – SaganRitual Mar 17 '18 at 19:55
  • About the debugger showing `p_B2` as a derived type: try setting `Base2* p_B2 = 0;` and see what the debugger says. It might be saying derived type because it is indeed pointing to a derived type. But that's just a guess. I recommend that you study the debugger documentation to find out how it displays derived types. – SaganRitual Mar 17 '18 at 19:59
  • @GreatBigBore Static cast: "Base2* p_B2 = &D;" I assumed base classes are laid out in memory in order of declaration. The debugger initially shows p_B2 as Base2* but after setting the value it changes to Derived*, so thats weird. – AdyAdy Mar 17 '18 at 20:12
  • 2
    That's not a `static_cast`. You get a `static_cast` by explicitly saying `static_cast`. As for assuming, don't do it. You can't know what the compiler is doing unless it's documented, or if you have the source code. – SaganRitual Mar 17 '18 at 20:15
  • You have an implicit conversion not a `static_cast` here => removed tag. – curiousguy Mar 30 '18 at 01:16

1 Answers1

3

The compiler is free to lay out your classes however it likes, presumably your compiler always puts virtual classes at the beginning and any non-virtual classes after that.

You can't rely on any particular ordering of classes.

Alan Birtles
  • 32,622
  • 4
  • 31
  • 60