C 语言实现 C++ 多态
来源:互联网 发布:金魔方软件 编辑:程序博客网 时间:2024/06/05 09:14
C 还是 C++?
C++ 中的多态是指「通过基类对象的指针或者基类对象的引用调用虚函数」,表现更多派生类的特性,但根据 C++ 多态的实现,我们发现这种方法存在一定的空间和效率的折损。不可否认,多态轻松解决了很多工程中遇到的问题,这与 pure C 的解决方法比起来,更为优雅。
在考虑移植性上,C 的光芒要盖过 C++,但 C++ 的多态是可借鉴的,于是用 pure C 来模仿 C++ 中多态行为。
C 如何实现多态
在 C 中没有类的概念,但有 struct,而且 C 中的 struct 是不允许有函数的,只允许存在变量,那是不是函数变量就允许存在了?!所以,函数指针可以给我们一些提示。
假定有一个结构体 struct Animal 声明如下:
struct
Animal
{
void
(*move)();
};
此时 Animal 中的 move 只是一个指针,并没有赋值,也就是说它不能代表任何的行为,但我们可以在 main 函数中对其进行赋值,赋予相应的行为。
void
Animal_move()
{
printf
(
"Animal move.\n"
);
}
再假定一个结构体 struct Rabbit,我们可以暂且把它看作(因为 C 中没有继承概念)struct Animal 的派生类,声明如下:
struct
Rabbit
{
void
(*move)();
};
同样我们可以给 Rabbit 的 move 预定义一个行为:
void
Rabbit_move()
{
printf
(
"Rabbit move.\n"
);
}
struct Animal 和 struct Rabbit 在内容上完全一致,而且变量对齐上也完全一致,可以通过将 struct Rabbit 类型的指针强制转换为 struct Animal 类型的指针,即:
Animal *panimal;
Rabbit rabbit;
//...
panimal = (Animal*)&rabbit;
这样,我们就可以通过 struct Animal 类型的指针或者引用来操纵 struct Rabbit 类型的对象了。
int
main(
void
)
{
Animal *panimal;
Rabbit rabbit;
rabbit.move=Rabbit_move;
panimal = (Animal*)&rabbit;
panimal->move();
}
Rabbit move.
请按任意键继续. . .
C 多态有什么问题
是不是有需要注意的问题?为什么刚才特别提出「在内容上完全一致,而且变量对齐上也完全一致」?倘若把 struct Animal 的声明作稍微的改变:
struct
Animal
{
int
age;
void
(*move)();
};
运行崩溃了,并不能得到上面的执行结果,原因是 move 函数指针 在struct Animal 中和 struct Rabbit 中的偏移量不同,结构体是根据变量在结构体的偏移量来读取或者修改变量的。当执行 panimal->move(); 的时候,实际上引用了非法的地址:
panimal->move();
可以被形象的转化为:
( * (panimal+sizeof(age)) ) ();
但发现 panimal 是指向 struct Rabbit 实体的,panimal+sizeof(age) 已经指向了非法地址:
struct Rabbit 结构调用void (*move )();<------ rabbit.move();非法地址<------ panimal->move();因此需要模拟多态,必须保持函数指针变量对齐。
在一些 c 开源项目中经常用到这种设计,譬如 libevent。
- C 语言实现 C++ 多态
- C语言实现C++多态
- C语言实现C++多态
- 链栈 C语言实现
- 地球 c语言实现
- C语言实现堆栈
- c语言实现计算器
- TrimLeft C语言实现
- C语言实现有限状态机
- 迪杰斯特拉 C语言实现
- C语言实现FIR
- C语言实现有限状态机
- C语言实现双链表
- C语言实现析构器
- C语言实现:万年历
- C语言实现有限状态机
- 二叉排序树 C语言实现
- C语言实现库函数
- strace
- 韩顺平老师算法连载4(转载)
- 烦人的 One or more breakpoints cannot be set and have been disabled.…… .
- 初学struts2框架,个人理解
- Zend Studio 配色方案插件
- C 语言实现 C++ 多态
- 2013.9.24去哪儿网西安地区笔试第一题
- Redhat Linux下如何生成core dump文件
- .NET导出Gridview到excel 带模板列显示
- Linux 中 crontab 详解及示例(收藏)
- 主要讨论Spring与Hibernate集成中的session问题
- CentOS ping: unknown host 解决方法
- Android Apk如何调用非系统jar包
- python 文件和路径操作函数小结 详细出处参考:http://www.jb51.net/article/21007.htm