c语言 面向对象 pdf,面向对象的C语言

本文介绍了如何在C语言中模拟面向对象编程的特性,如使用结构体实现对象,通过指针传递,手动实现继承和多态性。通过结构体嵌套实现继承,使用函数指针创建虚拟表(vtable)以达到多态效果。虽然这种方法不直观,但能够有效地在C语言中实现类似面向对象的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

我建议不要使用预处理器(Ab)来尝试使C语法更像另一种更面向对象的语言。在最基本的级别上,您只需使用普通的结构作为对象,并通过指针传递它们:struct monkey{

float age;

bool is_male;

int happiness;};void monkey_dance(struct monkey *monkey){

/* do a little dance */}

要获得诸如继承和多态性之类的东西,您必须更加努力地工作。您可以通过让结构的第一个成员成为超类的实例来进行手动继承,然后可以自由地围绕指向基类和派生类的指针进行转换:struct base{

/* base class members */};struct derived{

struct base super;

/* derived class members */};struct derived d;struct base *base_ptr = (struct base *)&d;

// upcaststruct derived *derived_ptr = (struct derived *)base_ptr;  // downcast

要获得多态性(即虚拟函数),可以使用函数指针和可选的函数指针表,也称为虚拟表或vtable:struct base;struct base_vtable{

void (*dance)(struct base *);

void (*jump)(struct base *, int how_high);};struct base{

struct base_vtable *vtable;

/* base members */};void base_dance(struct base *b){

b->vtable->dance(b);}void base_jump(struct base *b, int how_high){

b->vtable->jump(b, how_high);}struct derived1{

struct base super;

/* derived1 members */};void derived1_dance(struct derived1 *d){

/* implementation of derived1's dance function */}void derived1_jump(struct derived1 *d, int how_high){

/* implementation of derived 1's jump function */}/* global vtable for derived1 */struct base_vtable derived1_vtable ={

&derived1_dance, /* you might get a warning here about incompatible pointer types */

&derived1_jump   /* you can ignore it, or perform a cast to get rid of it */};void derived1_init(struct derived1 *d){

d->super.vtable = &derived1_vtable;

/* init base members d->super.foo */

/* init derived1 members d->foo */}struct derived2{

struct base super;

/* derived2 members */};void derived2_dance(struct derived2 *d){

/* implementation of derived2's dance function */}void derived2_jump(struct derived2 *d, int how_high){

/* implementation of derived2's jump function */}struct base_vtable derived2_vtable ={

&derived2_dance,

&derived2_jump};void derived2_init(struct derived2 *d){

d->super.vtable = &derived2_vtable;

/* init base members d->super.foo */

/* init derived1 members d->foo */}int main(void){

/* OK!  We're done with our declarations, now we can finally do some

polymorphism in C */

struct derived1 d1;

derived1_init(&d1);

struct derived2 d2;

derived2_init(&d2);

struct base *b1_ptr = (struct base *)&d1;

struct base *b2_ptr = (struct base *)&d2;

base_dance(b1_ptr);  /* calls derived1_dance */

base_dance(b2_ptr);  /* calls derived2_dance */

base_jump(b1_ptr, 42);  /* calls derived1_jump */

base_jump(b2_ptr, 42);  /* calls derived2_jump */

return 0;}

这就是你在C中做多态的方法,它不是很漂亮,但它做的是工作。在基类和派生类之间存在一些涉及指针转换的棘手问题,只要基类是派生类的第一个成员,这些问题就是安全的。多重继承要困难得多-在这种情况下,为了在第一个基类之间进行大小写,您需要根据适当的偏移量手动调整指针,这是非常棘手和容易出错的。

您可以做的另一件(棘手的)事情是在运行时更改对象的动态类型!您只需重新分配一个新的vtable指针。您甚至可以在保留其他函数的同时选择性地更改一些虚拟函数,从而创建新的混合类型。只是要小心地创建一个新的vtable,而不是修改全局vtable,否则会意外地影响到给定类型的所有对象。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值