Created
March 17, 2019 08:00
-
-
Save ear7h/848e8d7df7d862b9a3145e2c5ef0292b to your computer and use it in GitHub Desktop.
C++ virtual semantics
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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 originalc4
variable.