toophy原创, email : toophy@126.com, QQ : 1033683566, 工作几年积累的一点经验, 拿来夯实一下 :)
例子:
class CPlant
{
int age;
int height;
int weight;
int birth( int nheight, int nweight )
{
age = 0;
height = nheight;
weight = nweight;
return 1;
}
};
class CPotato : public CPlant
{
int wet;
int birth( int nheight, int nweight )
{
CPlant::birth(nheight,nweight);
wet = 0;
return 1;
}
int changewet( int nwet )
{
int old = wet;
wet = nwet;
return old;
}
};
class CAnimal
{
int age;
int height;
int weight;
int domain; // 地盘
int birth( int nheight, int nweight )
{
height = nheight;
weight = nweight;
age = 0;
domain = 0;
return 1;
}
int changedomain( int ndomain )
{
int old = domain;
domain = ndomain;
return old;
}
};
// 指针类型, 用于 birth
// 为了统一管理 birth 现象
typedef int(CPlant::*BIRTHPROC)(int,int);
// 声明, 可以保存为一个数组, 元素是 BIRTHPROC 指针
BIRTHPROC plantBirth;
BIRTHPROC potatoBirth;
BIRTHPROC animalBirth;
// 定义
plantBirth = &CPlant::birth;
potatoBirth = (BIRTHPROC)&CPotato::birth;
animalBirth = (BIRTHPROC)&CAnimal::birth;
CPlant plant;
CPotato potato;
CAnimal animal;
// 调用 **
(plant.*plantBirth)(10,2);
(potato.*potatoBirth)(6,4);
( ( (CPlant*)&animal )->*animalBirth )(100,30);
通过这个例子, 可以看出, 定义指针变量时只要使用 “强制转换” , 就可以通过编译, 注意赋值时候格式 “ & xxx :: FuncName “ , 就是取出函数跳转地址, 这样看来, 指针变量保存的
数据不过就是 函数跳转地址, 使用void* 也可以做到, 但是 后者在调用时候就很麻烦, 要写成 …..
调用时, 继承类型的好处是 : 和父类一样的调用方式. 没有任何关系的类型, 就要写成animal 的调用方式, 用 CPlant* 来强制转换来通过编译, 不要认为这样调用比上面两个慢,
其实, 汇编结果都一样, 如下
(plant.*plantBirth)(10,2);
push 2
push 10
lea ecx,[plant]
call dword ptr [plantBirth]
(potato.*potatoBirth)(6,4);
push 4
push 6
lea ecx,[potato]
call dword ptr [potatoBirth]
( ( (CPlant*)&animal )->*animalBirth )(100,30);
push 30
push 100
lea ecx,[animal]
call dword ptr [animalBirth]