#include class A { public: A() : w(1), v(2) {} virtual ~A() {} virtual void foo() { std::cout << "A::foo " << this << " " << w << std::endl; } virtual void quux() = 0; virtual void quuux(int a) { std::cout << "A::quuux " << this << " " << w << " " << a << std::endl; } private: int w, v; }; class B : public virtual A { public: B() { x = 3; } ~B() {} void foo() { std::cout << "B::foo " << this << " " << x << std::endl; } virtual void bar() { std::cout << "B::bar " << this << " " << x << std::endl; } void quux() { std::cout << "B::quux " << this << " " << x << std::endl; } private: int x; }; class C : public virtual A { public: C() { y = 4; } virtual void baz() { std::cout << "C::baz " << this << " " << y << std::endl; foo(); quux(); } private: int y; }; class D : public B, public C { public: D() { z = 5; } virtual void quux() { std::cout << "D::quux " << this << " " << z << std::endl; } private: int z; }; typedef void(*method)(A*, int); int main(int argc, char **argv) { B *b = new B(); D *d = new D(); // no pointer adjustment d->bar(); d->quux(); // pointer adjustment d->baz(); d->quuux(1); delete d; } /* An instance of D (gdb) x/12xw d 0x614ea0: 0x00401308 0x00000000 0x00000003 0x00000000 0x614eb0: 0x00401348 0x00000000 0x00000004 0x00000005 0x614ec0: 0x00401390 0x00000000 0x00000001 0x00000002 Its B vtable (gdb) x/8xg 0x4012f0 0x4012f0 <_ZTV1D>: 0x0000000000000020 0x0000000000000000 0x401300 <_ZTV1D+16>: 0x00000000004015f0 0x0000000000400d30 0x401310 <_ZTV1D+32>: 0x0000000000400d98 0x00000000004010fe 0x401320 <_ZTV1D+48>: 0x0000000000401166 0x00000000004011ec Its C vtable (gdb) x/8xg 0x401330 0x401330 <_ZTV1D+64>: 0x0000000000000010 0xfffffffffffffff0 0x401340 <_ZTV1D+80>: 0x00000000004015f0 0x0000000000400eaa 0x401350 <_ZTV1D+96>: 0x00000000004011da 0x0000000000401217 0x401360 <_ZTV1D+112>: 0x0000000000000000 0xffffffffffffffe0 Its A vtable (gdb) x/8xg 0x401378 0x401378 <_ZTV1D+136>: 0xffffffffffffffe0 0xffffffffffffffe0 0x401388 <_ZTV1D+152>: 0x00000000004015f0 0x00000000004011e0 0x401398 <_ZTV1D+168>: 0x000000000040121d 0x0000000000400d8e 0x4013a8 <_ZTV1D+184>: 0x000000000040115c 0x0000000000400c20 (gdb) x/1i 0x00000000004015f0 0x4015f0 <_ZTI1D>: test $0x1d,%al (gdb) x/1i 0x0000000000400d30 0x400d30 : push %rbp (gdb) x/1i 0x0000000000400d98 0x400d98 : push %rbp (gdb) x/1i 0x00000000004010fe 0x4010fe : push %rbp (gdb) x/1i 0x0000000000401166 0x401166 : push %rbp (gdb) x/1i 0x00000000004011ec 0x4011ec : push %rbp (gdb) x/1i 0x0000000000400eaa 0x400eaa : push %rbp (gdb) x/2i 0x00000000004011da 0x4011da <_ZThn16_N1DD1Ev>: sub $0x10,%rdi 0x4011de <_ZThn16_N1DD1Ev+4>: jmp 0x401166 (gdb) x/2i 0x0000000000401217 0x401217 <_ZThn16_N1DD0Ev>: sub $0x10,%rdi 0x40121b <_ZThn16_N1DD0Ev+4>: jmp 0x4011ec (gdb) x/3i 0x00000000004011e0 0x4011e0 <_ZTv0_n24_N1DD1Ev>: mov (%rdi),%r10 0x4011e3 <_ZTv0_n24_N1DD1Ev+3>: add -0x18(%r10),%rdi 0x4011e7 <_ZTv0_n24_N1DD1Ev+7>: jmpq 0x401166 (gdb) x/3i 0x000000000040121d 0x40121d <_ZTv0_n24_N1DD0Ev>: mov (%rdi),%r10 0x401220 <_ZTv0_n24_N1DD0Ev+3>: add -0x18(%r10),%rdi 0x401224 <_ZTv0_n24_N1DD0Ev+7>: jmp 0x4011ec (gdb) x/3i 0x0000000000400d8e 0x400d8e <_ZTv0_n32_N1B3fooEv>: mov (%rdi),%r10 0x400d91 <_ZTv0_n32_N1B3fooEv+3>: add -0x20(%r10),%rdi 0x400d95 <_ZTv0_n32_N1B3fooEv+7>: jmp 0x400d30 (gdb) x/3i 0x000000000040115c 0x40115c <_ZTv0_n40_N1D4quuxEv>: mov (%rdi),%r10 0x40115f <_ZTv0_n40_N1D4quuxEv+3>: add -0x28(%r10),%rdi 0x401163 <_ZTv0_n40_N1D4quuxEv+7>: jmp 0x4010fe (gdb) x/1i 0x0000000000400c20 0x400c20 : push %rbp (gdb) x/80i main ... 0x400a48 : mov -0x20(%rbp),%rdx 0x400a4c : mov -0x20(%rbp),%rax 0x400a50 : mov (%rax),%rax 0x400a53 : add $0x8,%rax 0x400a57 : mov (%rax),%rax 0x400a5a : mov %rdx,%rdi 0x400a5d : callq *%rax 0x400a5f : mov -0x20(%rbp),%rax 0x400a63 : mov (%rax),%rax 0x400a66 : add $0x10,%rax 0x400a6a : mov (%rax),%rax 0x400a6d : mov -0x20(%rbp),%rdx 0x400a71 : mov %rdx,%rdi 0x400a74 : callq *%rax 0x400a76 : mov -0x20(%rbp),%rax 0x400a7a : lea 0x10(%rax),%rdx 0x400a7e : mov -0x20(%rbp),%rax 0x400a82 : mov 0x10(%rax),%rax 0x400a86 : mov (%rax),%rax 0x400a89 : mov %rdx,%rdi 0x400a8c : callq *%rax 0x400a8e : mov -0x20(%rbp),%rax 0x400a92 : mov (%rax),%rax 0x400a95 : sub $0x18,%rax 0x400a99 : mov (%rax),%rax 0x400a9c : mov %rax,%rdx 0x400a9f : mov -0x20(%rbp),%rax 0x400aa3 : add %rax,%rdx 0x400aa6 : mov -0x20(%rbp),%rax 0x400aaa : mov (%rax),%rax 0x400aad : sub $0x18,%rax 0x400ab1 : mov (%rax),%rax 0x400ab4 : mov %rax,%rcx 0x400ab7 : mov -0x20(%rbp),%rax 0x400abb : add %rcx,%rax 0x400abe : mov (%rax),%rax 0x400ac1 : add $0x20,%rax 0x400ac5 : mov (%rax),%rax 0x400ac8 : mov $0x1,%esi 0x400acd : mov %rdx,%rdi 0x400ad0 : callq *%rax ... */