代码中所定义类的简单说明
C000:空类。
C010:带普通成员函数及/或变量的顶层类。
C011:带普通成员函数及/或变量的顶层类。
C012:带静态成员函数及变量的顶层类。
C013:从C010继承的有成员变量及覆盖父类普通成员函数的类。
C014:从C011继承的空类。
C015:从C010,C011继承的空类。
C016:从C015继承带成员函数及/或变量的类。
C020:从C010虚继承的带有自己的成员变量的类。
C021:从C010虚继承的带有自己的成员变量的类。
C030:从C020,C021继承的类。
C040:带虚函数的顶层类。
C041:带虚函数及变量的顶层类。
C042:带虚函数及变量的顶层类。
C043:带两个虚函数的顶层类。
C050:从C041继承的空类。
C051:从C041,C042继承的空类。
C071:从C043继承并重写父类第一个虚函数的类。
C082:从C041,C042继承带自己定义虚函数并重写父类的虚函数的类。
C100:从C041虚继承的带成员变量的类。
C101:从C041虚继承的带成员变量的类。
C110:从C100,C101继承的带成员变量的类。
C140:从C041虚继承并重写父类的虚函数的类。
C141:从C041虚继承并重写父类的虚函数的类。
C150:从C140,C141继承的类。
C160:从C041虚继承带有自定义虚函数并重写父类的虚函数的类。
C161:从C041虚继承带有自定义虚函数并重写父类的虚函数的类。
C170:从C160,C161继承的类。
源代码
附件为打包的源码和VC7.1工程文件,解开后可自己调度运行。
如果不下载附件请把所有的代码拷贝到一个CPP文件中即可。请注意用VC7.1进行编译(我只在VC7.1下验证过本代码)并一定把代码生成时的结构成员对齐选项设置为1字节,默认为8字节。否则运行时会有指针异常,请参见第一篇开始部分的说明。
(附件请到这里下载,在页面的最底端。)
#include
#include
using namespace std;
struct C000
{
};
struct C010
{
C010() : c_(0x01) {}
void foo() { c_ = 0x02; }
char c_;
};
struct C011
{
C011() : c1_(0x02), c2_(0x03) {}
char c1_;
char c2_;
};
struct C012
{
static int sfoo() { return 1; }
int foo() { return 1; }
char c_;
static int i_;
};
int C012::i_ = 1;
struct C013 : public C010
{
C013() : c1_(0x01) {}
void foo() { c1_ = 0x02; }
char c1_;
};
struct C014 : private C011
{
};
struct C015 : public C010, private C011
{
};
struct C016 : C015
{
C016() : i_(1) {}
int i_;
};
struct C020 : public virtual C010
{
C020() : c_(0x02) {}
char c_;
};
struct C021 : public virtual C010
{
C021() : c_(0x03) {}
char c_;
};
struct C030 : public C020, public C021
{
C030() : c_(0x04) {}
char c_;
};
struct C040
{
virtual void foo() {}
};
struct C041
{
C041() : c_(0x01) {}
virtual void foo() { c_ = 0x02; }
char c_;
};
struct C042
{
C042() : c_(0x02) {}
virtual void foo2() {}
char c_;
};
struct C043
{
virtual void foo1() {}
virtual void foo2() {}
};
struct C050 : C040
{
};
struct C051 : public C041, public C042
{
};
struct C071 : C043
{
virtual void foo1() {}
};
struct C082 : public C041, public C042
{
C082() : c_(0x03) {}
virtual void foo() {}
virtual void foo2() {}
virtual void foo3() {}
char c_;
};
struct C100 : public virtual C041
{
C100() : c_(0x02) {}
char c_;
};
struct C101 : public virtual C041
{
C101() : c_(0x03) {}
char c_;
};
struct C110 : public C100, public C101
{
C110() : c_(0x04) {}
char c_;
};
struct C140 : public virtual C041
{
C140() : c_(0x02) {}
virtual void foo() { c_ = 0x11; }
char c_;
};
struct C141 : public virtual C041
{
C141() : c_(0x03) {}
virtual void foo() { c_ = 0x12; }
char c_;
};
struct C150 : public C140, public C141
{
C150() : c_(0x04) {}
virtual void foo() { c_ = 0x21; }
char c_;
};
struct C160 : public virtual C041
{
C160() : c_(0x02) {}
virtual void foo() { c_ = 0x12; }
virtual void f160() { c_ = 0x12; }
char c_;
};
struct C161 : public virtual C041
{
C161() : c_(0x03) {}
virtual void foo() { c_ = 0x13; }
virtual void f161() { c_ = 0x13; }
char c_;
};
struct C170 : public C160, public C161
{
C170() : c_(0x04) {}
virtual void foo() { c_ = 0x14; }
virtual void f170() { c_ 0x14; }
char c_;
};
#define PRINT_SIZE(CLASS_NAME) \
cout << "The size of " << #CLASS_NAME << " is " << sizeof(CLASS_NAME) << endl;
#define PRINT_DETAIL(CLASS_NAME, OBJECT_NAME) \
cout << "The detail of " << #CLASS_NAME << " is "; \
for (int i = 0; i < sizeof(OBJECT_NAME); ++i) { \
cout.fill('0'); \
cout << setw(2) << hex << ((short)((char*)(&(OBJECT_NAME)))[i] & 0x00ff); \
cout << ' '; } \
cout << setw(0) << dec << endl;
#define PRINT_SIZE_DETAIL(CLASS_NAME) \
PRINT_SIZE(CLASS_NAME) \
CLASS_NAME _##CLASS_NAME; \
PRINT_DETAIL(CLASS_NAME, _##CLASS_NAME)
#define LF \
cout << endl;
template
void *
get_obj_addr(const T & obj)
{
return (void*)&obj;
}
void *
get_vp_addr(void * start, int offset)
{
return (void*)((char*)start + offset);
}
void *
get_vt_addr(void * vp)
{
return (void*)*((void**)vp);
}
void *
get_vti_val(void * vt, int idx)
{
return (void*)*((void**)((int*)vt + idx));
}
#define PRINT_VTABLE_ITEM(OBJ, VPOFFSET, INDEX) \
{ \
cout.fill(' '); \
cout << setw(8) << left; \
cout << #OBJ << " :"; \
void * obj_addr = get_obj_addr(OBJ); \
cout << hex << " objadr:" << obj_addr; \
void * vp_addr = get_vp_addr(obj_addr, VPOFFSET); \
cout << " vpadr:" << vp_addr; \
void * vt_addr = get_vt_addr(vp_addr); \
cout << " vtadr:" << vt_addr; \
void * vti_val = get_vti_val(vt_addr, INDEX); \
cout << " vtival(" << INDEX << "):" << vti_val << dec << right << endl; \
}
#define PRINT_OBJ_ADR(OBJ) \
cout << #OBJ << "'s address is : " << hex << get_obj_addr(OBJ) << dec << endl;
#define PRINT_PT(PT) \
cout << #PT << "'s value is : " << hex << PT << dec << endl;
struct __declspec(novtable) C180
//struct C180
{
C180() {
foo();
this->foo();
}
virtual foo() {
cout << "<< C180.foo this: " << this << " vtadr: " << *(void**)this << endl;
}
};
struct C190 : public C180
{
C190() {}
virtual foo() {
cout << "<< C190.foo this: " << this << " vtadr: " << *(void**)this << endl;
}
};
int
main(int argc, char * argv[])
{
PRINT_SIZE_DETAIL(C000)
LF
PRINT_SIZE_DETAIL(C010)
PRINT_SIZE_DETAIL(C011)
LF
PRINT_SIZE_DETAIL(C012)
LF
PRINT_SIZE_DETAIL(C013)
LF
PRINT_SIZE_DETAIL(C014)
PRINT_SIZE_DETAIL(C015)
LF
PRINT_SIZE_DETAIL(C016)
LF
PRINT_SIZE_DETAIL(C040)
LF
PRINT_SIZE_DETAIL(C050)
LF
PRINT_SIZE_DETAIL(C041)
{
LF
C040 obj1, obj2;
PRINT_VTABLE_ITEM(obj1, 0, 0)
PRINT_VTABLE_ITEM(obj2, 0, 0)
LF
C040 c040;
C050 c050;
PRINT_VTABLE_ITEM(c040, 0, 0)
PRINT_VTABLE_ITEM(c050, 0, 0)
}
{
LF
C043 c043;
C071 c071;
PRINT_SIZE_DETAIL(C071)
PRINT_VTABLE_ITEM(c043, 0, 0)
PRINT_VTABLE_ITEM(c071, 0, 0)
PRINT_VTABLE_ITEM(c043, 0, 1)
PRINT_VTABLE_ITEM(c071, 0, 1)
}
{
LF
PRINT_SIZE_DETAIL(C041)
PRINT_SIZE_DETAIL(C042)
PRINT_SIZE_DETAIL(C051)
C041 c041;
C042 c042;
C051 c051;
PRINT_VTABLE_ITEM(c041, 0, 0)
PRINT_VTABLE_ITEM(c042, 0, 0)
PRINT_VTABLE_ITEM(c051, 0, 0)
PRINT_VTABLE_ITEM(c051, 5, 0)
}
{
LF
PRINT_SIZE_DETAIL(C082)
C041 c041;
C042 c042;
C082 c082;
PRINT_VTABLE_ITEM(c041, 0, 0)
PRINT_VTABLE_ITEM(c042, 0, 0)
PRINT_VTABLE_ITEM(c082, 0, 0)
PRINT_VTABLE_ITEM(c082, 5, 0)
PRINT_VTABLE_ITEM(c082, 0, 1)
PRINT_VTABLE_ITEM(c082, 5, 1)
c082.foo3();
c082.C041::c_ = 0x05;
PRINT_VTABLE_ITEM(c041, 0, 0)
PRINT_DETAIL(C041, ((C041)c082))
PRINT_VTABLE_ITEM(((C041)c082), 0, 0)
LF
PRINT_VTABLE_ITEM(c082, 5, 0)
C042 * pt = dynamic_cast(&c082);
PRINT_VTABLE_ITEM(*pt, 0, 0)
}
//PK change object's type by force
{
LF
C013 obj;
obj.foo();
((C010)obj).foo();
obj.C010::foo();
}
{
LF
C010 obj;
PRINT_OBJ_ADR(obj)
obj.foo();
C012::sfoo();
C010 * pt = &obj;
pt->foo();
}
{
LF
cout << "<>" << endl;
C041 obj;
PRINT_DETAIL(C041, obj)
PRINT_VTABLE_ITEM(obj, 0, 0)
obj.foo();
C041 * pt = &obj;
pt->foo();
}
{
LF
C051 obj;
C041 * pt1 = dynamic_cast(&obj);
C042 * pt2 = dynamic_cast(&obj);
pt1->foo();
pt2->foo2();
}
{
LF
C190 obj;
obj.foo();
PRINT_DETAIL(C190, obj);
PRINT_OBJ_ADR(obj);
}
{
LF
PRINT_SIZE_DETAIL(C020)
PRINT_SIZE_DETAIL(C030)
PRINT_SIZE_DETAIL(C100)
PRINT_SIZE_DETAIL(C110)
C020 c020;
c020.C010::c_ = 0x04;
PRINT_OBJ_ADR(c020);
C010 * pt = &c020;
PRINT_PT(pt);
pt->c_ = 0x03;
C010 * pt1 = 0;
C010 * pt2 = pt1;
C110 c110;
c110.c_ = 0x51;
c110.C100::c_ = 0x52;
c110.C101::c_ = 0x52;
c110.C041::c_ = 0x53;
c110.foo();
}
{
LF
PRINT_SIZE_DETAIL(C041)
PRINT_SIZE_DETAIL(C140)
PRINT_SIZE_DETAIL(C141)
PRINT_SIZE_DETAIL(C150)
C150 obj;
PRINT_OBJ_ADR(obj)
obj.foo();
C150 * pt = &obj;
pt->foo();
C141 * pt1 = dynamic_cast(pt);
pt1->foo();
}
{
LF
PRINT_SIZE_DETAIL(C041)
PRINT_SIZE_DETAIL(C160)
PRINT_SIZE_DETAIL(C161)
PRINT_SIZE_DETAIL(C170)
C170 obj;
PRINT_OBJ_ADR(obj);
obj.foo();
obj.f170();
C170 * pt = &obj;
pt->f170();
pt->C041::c_ = 0x33;
C161 * pt2 = dynamic_cast(pt);
pt2->c_ = 0x34;
pt2->foo();
pt2->f161();
}
return 0;
}