一 代码
#include "stdafx.h"
#include <iostream>
using namespace std;
typedef void (*pFunc)();
class MyBase{
public:
virtual void vfunA() {
std::cout << "call MyBase::vfunA" << std::endl;
}
virtual void vfunB() {
std::cout << "call MyBase::vfunB" << std::endl;
}
void funC() {
std::cout << "call MyBase::funC" << std::endl;
}
void funD() {
std::cout << "call MyBase::funD" << std::endl;
}
public:
int m_a;
int m_b;
};
class MyDerived : public MyBase{
public:
virtual void vfunA() {
std::cout << "call MyDerived::vfunA" << std::endl;
}
/*
virtual void vfunB() {
std::cout << "call MyDerived::vfunB" << std::endl;
}
*/
void funD1() {
std::cout << "call MyDerived::funD1" << std::endl;
}
public:
int m_c;
int m_d;
};
int main() {
std::cout << "hello,world!" << std::endl;
std::cout << "打印基类的内存结构" << std::endl;
MyBase baseObj;
std::cout << "1: 占用内存" << std::endl;
std::cout << "sizeof(baseObj) = "<< sizeof(baseObj) << std::endl;
std::cout << "2: 对象首地址" << std::endl;
std::cout << "&baseObj = " << &baseObj << std::endl;
std::cout << "3: 对象虚函数地址" << std::endl;
//首先获取obj的地址,也即内存首地址,首地址中存放的是指针(vptr),所以p 实际上就是指针的指针
void **p = (void **)&baseObj;
//*p取得的是vptr的值,vptr指向虚函数表,虚函数表中存放的是指针(函数指针),所以vptr实际上也是指针的指针
void **vptr = (void **)*p; //相当于 void *vptr[]; 表明是一个数组,数组中存放的是指针
printf("obj MyDerived::vfunA: %p\n", vptr[0]); //第一个虚函数的函数指针
pFunc vfunAObj = (pFunc)*((int*)(vptr+0));
vfunAObj();
printf("obj MyDerived::vfunB: %p\n", vptr[1]); //第二个虚函数的函数指针
pFunc vfunBObj = (pFunc)*((int*)(vptr+1));
vfunBObj();
cout << "4: 对象成员函数地址" << endl;
printf("MyBase::funC() \t addr: 0x%p\n", &MyBase::funC);
printf("MyBase::funD() \t addr: 0x%p\n", &MyBase::funD);
cout << "5: 对象成员变量地址" << endl;
printf("&baseObj.m_a \t addr: 0x%p\n", &baseObj.m_a);
printf("&baseObj.m_b \t addr: 0x%p\n", &baseObj.m_b);
std::cout << "打印派生类的内存结构" << std::endl;
MyDerived derivedObj;
std::cout << "1: 占用内存" << std::endl;
std::cout << "sizeof(derivedObj) = "<< sizeof(derivedObj) << std::endl;
std::cout << "2: 对象首地址" << std::endl;
std::cout << "&derivedObj = " << &derivedObj << std::endl;
std::cout << "3: 对象虚函数地址" << std::endl;
//首先获取obj的地址,也即内存首地址,首地址中存放的是指针(vptr),所以p 实际上就是指针的指针
void **p1 = (void **)&derivedObj;
//*p取得的是vptr的值,vptr指向虚函数表,虚函数表中存放的是指针(函数指针),所以vptr实际上也是指针的指针
void **vptr1 = (void **)*p1; //相当于 void *vptr[]; 表明是一个数组,数组中存放的是指针
printf("obj MyDerived::vfunA: %p\n", vptr1[0]); //第一个虚函数的函数指针
printf("obj MyDerived::vfunB: %p\n", vptr1[1]); //第二个虚函数的函数指针
cout << "4: 对象成员函数地址" << endl;
printf("MyDerived::funC() \t addr: 0x%p\n", &MyDerived::funC);
printf("MyDerived::funD() \t addr: 0x%p\n", &MyDerived::funD);
printf("MyDerived::funD1() \t addr: 0x%p\n", &MyDerived::funD1);
cout << "5: 对象成员变量地址" << endl;
printf("&derivedObj.m_a \t addr: 0x%p\n", &derivedObj.m_a);
printf("&derivedObj.m_b \t addr: 0x%p\n", &derivedObj.m_b);
printf("&derivedObj.m_c \t addr: 0x%p\n", &derivedObj.m_c);
printf("&derivedObj.m_d \t addr: 0x%p\n", &derivedObj.m_d);
return 0;
}
hello,world!
打印基类的内存结构
1: 占用内存
sizeof(baseObj) = 12
2: 对象首地址
&baseObj = 0054FB0C
3: 对象虚函数地址
obj MyDerived::vfunA: 00591032
call MyBase::vfunA
obj MyDerived::vfunB: 00591181
call MyBase::vfunB
4: 对象成员函数地址
MyBase::funC() addr: 0x00591014
MyBase::funD() addr: 0x0059100A
5: 对象成员变量地址
&baseObj.m_a addr: 0x0054FB10
&baseObj.m_b addr: 0x0054FB14
打印派生类的内存结构
1: 占用内存
sizeof(derivedObj) = 20
2: 对象首地址
&derivedObj = 0054FAC0
3: 对象虚函数地址
obj MyDerived::vfunA: 0059108C
obj MyDerived::vfunB: 00591181
4: 对象成员函数地址
MyDerived::funC() addr: 0x00591014
MyDerived::funD() addr: 0x0059100A
MyDerived::funD1() addr: 0x0059109B
5: 对象成员变量地址
&derivedObj.m_a addr: 0x0054FAC4
&derivedObj.m_b addr: 0x0054FAC8
&derivedObj.m_c addr: 0x0054FACC
&derivedObj.m_d addr: 0x0054FAD0
请按任意键继续. . .
二 类继承的内存结构
网上找的相似的类图,后续有时间再补上新图,和详细讲解。