Listing 4: | Cequivalentcodeoflisting3 |
1enum { X_id, Y_id
};
2struct X;
// forward declaration of X 3struct Y;
// forward declaration of Y 4 5void X_m1(
struct X
*this);
6void X_m2(
struct X
*this);
7void Y_m2(
struct Y
*this);
8void Y_m3(
struct Y
*this);
9 10struct X_vtable
11{ 12 int id;
13 void (
*m1)(
struct X
*this);
14 int offset_m1;
15 void (
*m2)(
struct X
*this);
16 int offset_m2;
17} _X_vtable =
{ X_id, X_m1, 0, X_m2, 0
};
18 19struct YX_vtable
20{ 21 int id;
22 void (
*m1)(
struct X
*this);
23 int offset_m1;
24 void (
*m2)(
struct Y
*this);
25 int offset_m2;
26 void (
*m3)(
struct Y
*this);
27 int offset_m3;
28} _YX_vtable =
{ Y_id, X_m1, 8, Y_m2, 0, Y_m3, 0
};
29 30struct X
31{ 32 struct X_vtable
*pVtable;
33 int derived_offset;
34 int n;
35};
36 37struct Y
38{ 39 struct YX_vtable
*pVtableX;
40 int derived_offset;
41 struct X superX;
42 int m;
43};
44 45void test(
void)
46{ 47 struct X myX;
48 struct Y myY;
49 struct X
*pX;
50 struct Y
*pY;
51 52 // constructor code to initialize points to vtables 53 myX.pVtable = &_X_vtable;
54 myX.derived_offset = 0;
55 myY.pVtableX = &_YX_vtable;
56 myY.derived_offset = 0;
57 myY.superX.pVtable = (
struct _X_vtable
*)&_YX_vtable;
// changed on 20061109 58 myY.superX.derived_offset =
−8;
59 // end constructor code 60 X_m1(&myX);
61 X_m1(&myY.superX);
62 Y_m2(&myY);
63 pX = &myY.superX;
// static up cast 64 { 65 struct X_vtable
*vtab = pX
−>pVtable;
// changed on 20061109 66 vtab
−>m1((((
char *)pX)+pX
−>derived_offset+vtab
−>offset_m1));
// compiler won’t like the pointer type 67 } 68 { 69 struct X_vtable
*vtab = pX
−>pVtable;
// changed on 20061109 70 vtab
−>m2((((
char *)pX)+pX
−>derived_offset+vtab
−>offset_m2));
// compiler won’t like the pointer type 71 } 72 { 73 // dynamic down cast code 74 pY = (
struct Y
*)
75 (((
char *)pX)
− 76 sizeof(YX_vtable
*));
77 if (pY
−>pVtableX
−>id != Y_id) pY = 0;
78 } 79 if (pY) pY
−>pVtableX
−>m3(pY);
80}
There are quite a few interesting things going on here in the C equivalent code for a polymorphic class
hierarchy.