Skip to content

Instantly share code, notes, and snippets.

@ear7h
Created March 17, 2019 08:00
Show Gist options
  • Save ear7h/848e8d7df7d862b9a3145e2c5ef0292b to your computer and use it in GitHub Desktop.
Save ear7h/848e8d7df7d862b9a3145e2c5ef0292b to your computer and use it in GitHub Desktop.
C++ virtual semantics
void * 8
C0 4
C1 16
C11 8
C2 24
C3 8
C4 32
pt 32
c4->a 0x101457120
c4->b 0xab
c4->c 0x101457140
c4->d 0x101457158
C4 ma
C4 mb
c1->a 0x1014571e8
c1->b 0xab
C1 ma
c3->a 0x101457200
C3 mb
c11->a 0x101457218
C11 ma
refc1->a 0x101457120
refc1->b 0xab
C4 ma
refc3->a 0x101457140
C4 mb
refc11->a 0x101457158
C4 ma
#include <iostream>
using namespace std;
class C0 {
public:
int fb; // not 8 byte align
C0(): fb(0xaa) {}
void ma() {
cout << "C1 ma" << endl;
}
void mb() {
cout << "C2 mb" << endl;
}
};
class C1 {
public:
long fa;
C1() : fa(0xab) {}
virtual void ma() {
cout << "C1 ma" << endl;
}
};
class C11 {
public:
virtual void ma() {
cout << "C11 ma" << endl;
}
};
class C2 : public C1 {
public:
long fa; // new variable, shadowing parent fa
C2() : fa(0xac) {}
void ma() {
cout << "C2 ma" << endl;
}
};
class C3 {
public:
virtual void mb() {
cout << "C3 mb" << endl;
}
};
class C4: public C1, public C3, public C11 { // 3 virtual pointers, 1 for each parent class
public:
void ma() {
cout << "C4 ma" << endl;
}
void mb() {
cout << "C4 mb" << endl;
}
};
typedef struct {
void * a;
void * b;
void * c;
void * d;
} pointers;
int main() {
cout << "void * " << sizeof(void *) << endl;
cout << "C0 " << sizeof(C0) << endl;
cout << "C1 " << sizeof(C1) << endl;
cout << "C11 " << sizeof(C11) << endl;
cout << "C2 " << sizeof(C2) << endl;
cout << "C3 " << sizeof(C3) << endl;
cout << "C4 " << sizeof(C4) << endl;
cout << "pt " << sizeof(pointers) << endl;
cout << endl;
C4 c4 = C4();
cout << "c4->a " << ((pointers *) (&c4))->a << endl;
cout << "c4->b " << ((pointers *) (&c4))->b << endl;
cout << "c4->c " << ((pointers *) (&c4))->c << endl;
cout << "c4->d " << ((pointers *) (&c4))->d << endl;
c4.ma();
c4.mb();
cout << endl;
// stack vars
C1 c1 = c4;
cout << "c1->a " << ((pointers *) (&c1))->a << endl;
cout << "c1->b " << ((pointers *) (&c1))->b << endl;
c1.ma();
C3 c3 = c4;
cout << "c3->a " << ((pointers *) (&c3))->a << endl;
c3.mb();
C11 c11 = c4;
cout << "c11->a " << ((pointers *) (&c11))->a << endl;
c11.ma();
cout << endl;
// references
C1 &refc1 = c4;
cout << "refc1->a " << ((pointers *) (&refc1))->a << endl;
cout << "refc1->b " << ((pointers *) (&refc1))->b << endl;
refc1.ma();
C3 &refc3 = c4;
cout << "refc3->a " << ((pointers *) (&refc3))->a << endl;
refc3.mb();
C11 &refc11 = c4;
cout << "refc11->a " << ((pointers *) (&refc11))->a << endl;
refc11.ma();
}
@ear7h
Copy link
Author

ear7h commented Mar 17, 2019

A basic program to show some semantics and workings of C++ polymorphism. One surprise was that the stack allocated variables aren't dynamically polymorphic. This SO answer offers some insight, it seems as this is purely a semantic choice by C++ authors. Otherwise note that the reference variables have the same vpointers as the original c4 variable.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment