能力值:
( LV4,RANK:50 )
|
-
-
2 楼
本文的 openoffice 文档在 http://bbs.pediy.com/showthread.php?t=185650
|
能力值:
( LV3,RANK:20 )
|
-
-
3 楼
谢谢楼主,最近在看C++反汇编。嘿嘿。还没看到对象,努力中。。。
|
能力值:
( LV6,RANK:90 )
|
-
-
4 楼
//声明函数指针
typedef double (WINAPIV *CALC_AREA)(void*);
//------------基类-----------
//虚表
struct Shape_Vt
{
//这里定义一系列的虚拟成员函数
CALC_AREA fnArea;
}
//原型
struct Shape
{
//基类虚表,将被子类虚表覆盖,以实现多态
Shape_Vt* pVt;
//这个成员是自定义,来保存子类对象 在C++中肯定是不存在此类成员的
void* pObject;
}
//--------------------------
//-----------圆---------------
//每一个带虚拟成员(包括继承)都有自己的虚表
//虚表
struct Circle_Vt
{
//首先要包含基类的虚表成员,索引和定义要和基类一致,但有不同的实现过程
//本类的虚拟成员函数列于基类的虚拟成员函数后面
CALC_AREA fnArea;
}
//原型
struct Circle
{
//虚表指针 可同时被下一级的子类覆盖,来实现更丰富的多态
Circle_Vt* pVt;
double radius;
}
//实现
double Circle_area(void* pObject)
{
pCir = (Circle*)pObject;
return 3.14*pCir->radius*pCir->radius;
}
//---------------------------
//------------正方形----------
//虚表
struct Square_Vt
{
CALC_AREA fnArea;
}
//原型
struct Square
{
Square_Vt* pVt;
double s;
}
//实现
double Square_area(void* pObject)
{
pS = (Square*)pObject;
return pS->s*pS->s;
}
//----------------------------
//------------长方形---------
//虚表
struct Rectangle_Vt
{
CALC_AREA fnArea;
}
//原型
struct Rectangle{
Rectangle_Vt* pVt;
double width;
double length;
};
//实现
double Rectangle_area(void* pObject)
{
pR = (Rectangle*)pObject;
return pR->length*pR->width;
}
//------------------------
int main()
{
//声明3个基类
Shape shape[3];
//声明一个子类 里面的数据成员初始化省了 下同
Circle cir;
//初始化虚表
cir.pVt = &Circle_Vt;
//初始化虚表元素,其实这个是在编译期就初始化好的应该
Circle_Vt.fnArea = Circle_area;
//将基类的虚表覆盖
shape[0].pVt = cir.pVt;
//设置对象
shape[0].pObject = (void*)○
Square square;
square.pVt = &Square_Vt;
Square_Vt.fnArea = Square_area;
shape[1].pVt = square.pVt;
shape[1].pObject = (void*)□
Rectangle rect;
rect.pVt = &Rectangle_Vt;
Rectangle_Vt.fnArea = Rectangle_area;
shape[2].pVt = rect.pVt;
shape[2].pObject = (void*)▭
//调用
//虽然看起来和把shape转成Circle等对象指针调用更直接点
//但事实上,内存确是这样操作
//汇编代码大概是这样
//mov eax,dword ptr ds:[ecx] ;ecx指向Circle等对象 此时获得虚表指针 eax=shape.pVt;
//mov edx,dword ptr ds:[eax] ;通过这个虚表指针获取函数地址 edx=shape.pVt->fnArea
//call edx ;调用这个函数 shape.pVt->fnArea();
//C的过程大概是这样
//mov eax,dword ptr ds:[ecx] ;eax=shape.pVt; ecx=shape
//mov edx,dword ptr ds:[eax] ;edx=shape.pVt->fnArea
//push dword ptr ds:[ecx+4] ; 即push shape.pObject 但因 为C没有对象的概念,所以此时要把对象作参数调用 这里默认
//call edx ;shape.pVt->fnArea(shape.pObject);
//add esp,4
//事实上C更多是这样调用
//push dword ptr ds:[ecx+4]
//CALL 004XXXXXX
//add esp,4
for(int i=0;i<3;i++)
{
printf("%f\n",shape[i].pVt->fnArea(shape[i].pObject));
}
//以上可以看出,所谓的多态其实 就是虚表的替换,不同的虚表保存各类型的实现过程
//C++在退出函数执行析构时 会把虚表写回来 然后调用相关的析构过程
shape[0].pVt = &Shape_Vt;
shape[1].pVt = &Shape_Vt;
shape[2].pVt = &Shape_Vt;
}
|
能力值:
( LV2,RANK:10 )
|
-
-
5 楼
如果你想要面向对象特性,请使用C++或者使用宏进行封装。后一种请参考http://www.codeproject.com/Articles/13601/COM-in-plain-C
|
能力值:
( LV2,RANK:10 )
|
-
-
6 楼
这个可以看看,感谢楼主
|
能力值:
( LV2,RANK:10 )
|
-
-
7 楼
好文,看看vfs的实现,这种写法到处都是。
|
能力值:
( LV3,RANK:20 )
|
-
-
8 楼
好厉害的样子 不懂
|
能力值:
( LV4,RANK:50 )
|
-
-
9 楼
谢谢luci的详细回复,我下次发这种帖子的时候尽量些详细点哈。
|
能力值:
( LV2,RANK:10 )
|
-
-
10 楼
感谢楼主开出这个题。luci的方法更详细。
|
|
|