C语言的继承与多态

这篇文章旨在记录自己对C语言的封装、继承与多态的学习过程,参考了优快云上的一篇博客,本来要贴出来地址,无奈无痕浏览模式下找不到在哪里了。不过这并不影响我的分享。

对于继承和多态,我这里不做解释,看到这篇文章自然有一定的基础,解释自然是多余了。既然有基础了,那我直接上代码,供伙伴们查看和觉悟即可。

为方便无基础的伙伴,还是要提点一下关键,至少看不懂的时候,可快速自检自己的知识盲区。阅读源码的基础如下:

1. 熟悉C/C++语言,至少其中一种。

2. 了解内存模型,学习过C++的,自然看一下就明白了。


源码来了:

//Animal.h

#ifndef _ANIMAL_H_
#define __ANIMAL_H_

//add virtual tables
struct AnimalVTable;

//def parent struct
typedef struct {
    struct AnimalVTable *vptr;//pointer to vritual table
    int Age;
    int Weight;
}Animal;

//virtual table
struct AnimalVTable{
    void (*say)(Animal* this);// virtual functions pointer
    void (*action)(Animal* this);

};

//parent virtual fun realization
void Animal_Say(Animal* this);
void Animal_Action(Animal* this);


//declare constructor
void Animal_Ctor(Animal* this,int age,int weight);

//functions for getting parent's members
int Animal_GetAge(Animal* this);
int Animal_GetWeight(Animal* this);

//functions for setting parents' members
void Animal_SetAge(Animal* this,int age);
void Animal_SetWeight(Animal* this,int weight);

#endif
//Animal.c

#include"Animal.h"
#include<assert.h>
#include<stdio.h>

//parent virtual fun realization
static void _Animal_Say(Animal* this)
{
    printf("Animal say\n");
    // assert(0);
}
//parent virtual fun realization
static void _Animal_Action(Animal* this)
{
    printf("Animal action\n");
    // assert(0);
}


void Animal_Ctor(Animal* this,int age,int weight)
{
    static struct AnimalVTable animal_vptr={_Animal_Say,_Animal_Action};
    this->vptr=&animal_vptr;
    this->Age=age;
    this->Weight=weight;
}

int Animal_GetAge(Animal* this)
{
    return this->Age;
}
int Animal_GetWeight(Animal* this)
{
    return this->Weight;
}

void Animal_SetAge(Animal* this,int age)
{
    this->Age=age;
}
void Animal_SetWeight(Animal* this,int weight)
{
    this->Weight=weight;
}

void Animal_Say(Animal* this)
{
    this->vptr->say(this);
}
void Animal_Action(Animal* this)
{
    this->vptr->action(this);
}
//Dog.h
#ifndef _DOG_H_
#define _DOG_H_

// #include"Animal.h"
struct Animal;

//def child stuct
typedef struct{
    Animal parent;
    int Legs;
}Dog;

//constructor
void Dog_Ctor(Dog* this,int age,int weight,int legs);

int Dog_GetAge(Dog* this);
int Dog_GetWeight(Dog* this);
int Dog_GetLegs(Dog* this);


#endif
//Dog.c
#include"Animal.h"
#include"Dog.h"
#include"stdio.h"

static void _Dog_Say(Dog *this)
{
    printf("today dog say\n");
}
static void _Dog_Action(Dog *this)
{
    printf("today dog action\n");
}
//constructor
void Dog_Ctor(Dog* this,int age,int weight,int legs)
{
    Animal_Ctor(&this->parent,age,weight);
    static struct AnimalVTable dog_vtbl={_Dog_Say,_Dog_Action};
    this->parent.vptr=&dog_vtbl;
    this->Legs=legs;
}


int Dog_GetAge(Dog* this)
{
    return Animal_GetAge(&this->parent);
}
int Dog_GetWeight(Dog* this)
{
    return Animal_GetWeight(&this->parent);
}
int Dog_GetLegs(Dog* this)
{
    return this->Legs;
}
//Test code main.c
#include<stdio.h>

#include"Animal.h"
#include"Dog.h"

int main(int argc,char** argv)
{
    Dog an;
    Dog_Ctor(&an,1,6,4);

    Animal* pa=(Animal*)&an;
    Animal_Say(pa);
    Animal_Action(pa);

    Animal aa;
    Animal_Ctor(&aa,1,6);
    Animal_Say(&aa);
    Animal_Action(&aa);
    //printf("age=%d,weight=%d,legs=%d\n",Dog_GetAge(&an),Dog_GetWeight(&an),Dog_GetLegs(&an));
    return 0;
}

执行测试输出

today dog say
today dog action
Animal say
Animal action

编译的话用cmake,编译文件如下:

cmake_minimum_required(VERSION 3.16)
project(c_opp)

file(GLOB SRCS ${CMAKE_CURRENT_SOURCE_DIR}/*.c)
message(${SRCS})
add_executable(${PROJECT_NAME} ${SRCS})

至于编译指令就自行搜索了

<think>好的,我现在要回答用户关于OCP和OPP的概念及其区别的问题。首先,我需要明确这两个缩写代表什么。OCP通常指开闭原则(Open-Closed Principle),而OPP可能是面向过程编程(Procedural Programming)的缩写,但用户提到的引用中提到了DIP(依赖倒置原则)和OPP的对比,所以这里可能OPP是指面向过程编程,或者用户可能有拼写错误?比如OOP(面向对象编程)? 不过根据用户提供的引用内容,里面提到“有人说依赖反转是 OOP 和 OPP 的分水岭”,这里OOP是面向对象,而OPP可能是面向过程编程(Procedural Programming)。所以用户的问题应该是关于开闭原则(OCP)和面向过程编程(OPP)的区别,或者可能用户混淆了术语? 首先,我需要确认OCP和OPP各自的定义: OCP(开闭原则):属于SOLID原则之一,由Bertrand Meyer提出,核心是软件实体应对扩展开放,对修改关闭。即在不修改现有代码的情况下扩展功能。 OPP如果是面向过程编程,则是以过程(函数)为中心的编程范式,例如C语言。而OOP是面向对象,以对象和类为基础。 用户提供的引用中提到DIP是OOP和OPP的分水岭,说明OPP在这里指面向过程编程。但用户的问题是关于OCPOPP的区别,所以需要解释这两个概念的不同。 可能用户将OCP误写为OCP,而实际是想问OOP和OPP的区别?但根据问题描述,用户明确询问的是OCP和OPP,因此需要按此回答。 接下来,我需要整理OCP和OPP的概念,并指出它们的区别。同时,引用中的例子涉及依赖倒置原则,可能需要关联到OCP在OOP中的体现,说明OCP属于OOP的设计原则之一,而OPP是另一种编程范式,两者的区别在于设计理念和结构。 然后,生成相关问题,例如关于SOLID原则的其他内容,OCP的实现方法,面向过程面向对象的比较等。 需要确保回答结构清晰,使用中文,正确使用LaTeX格式,比如提到原则时可能需要数学表达式,如$...$,但可能这里内容不需要太多公式,但需注意用户提到的系统级指令中的格式要求,比如行内数学表达式用$...$,独立公式用$$...$$,但这里可能不涉及太多数学内容,但需要检查。 最后,引用用户提供的参考中的例子,说明在OPP中高层模块依赖底层,而OOP通过依赖倒置解耦,这可能关联到OCP的应用,因为OCP提倡通过扩展而非修改来增加功能,依赖倒置有助于实现这一点。 总结回答结构: 1. 定义OCP(开闭原则)及其在OOP中的作用。 2. 定义OPP(面向过程编程)的特点。 3. 对比两者的区别,如设计理念、依赖关系、扩展方式。 4. 引用中的例子说明OPP中的依赖问题,OOP如何通过DIP和OCP解决。 5. 相关问题部分生成相关的问题,如OCP的实现方式,OPPOOP的区别等。 需要注意引用标识,例如在提到依赖关系时引用[^1]。</think>### OCPOPP的概念及区别 #### 1. OCP(开闭原则) **OCP(Open-Closed Principle,开闭原则)** 是面向对象编程(OOP)中SOLID设计原则之一,由Bertrand Meyer提出。其核心思想是: > **软件实体(类、模块、函数等)应对扩展开放,对修改关闭**。 这意味着在不修改现有代码的前提下,通过扩展(如继承、接口实现、组合)来增加新功能。例如,若系统需要支持新的支付方式,应通过添加新类而非修改原有支付逻辑实现[^1]。 #### 2. OPP(面向过程编程) **OPP(Procedural Programming,面向过程编程)** 是一种以**过程(函数)为中心**的编程范式,典型语言如C。其特点是: - 程序由一系列函数组成,数据操作分离。 - 高层逻辑直接依赖底层实现,例如外卖场景中,若赔付逻辑需要修改(如代金券改为现金),可能需直接修改调用赔付函数的代码[^1]。 #### 3. 核心区别 | 维度 | OCP(开闭原则) | OPP(面向过程编程) | |-------------|-------------------------------|---------------------------| | **设计目标** | 增强扩展性,减少修改风险 | 强调步骤分解和函数调用 | | **依赖关系** | 通过抽象(接口/基类)解耦 | 高层逻辑直接依赖底层实现[^1] | | **扩展方式** | 新增代码(继承、组合等) | 通常需修改现有函数或流程 | | **应用场景** | 复杂系统、需求频繁变更的场景 | 简单任务或性能敏感场景 | #### 示例对比 - **OPP的局限性**: 若外卖赔付逻辑从代金券改为现金,需直接修改调用赔付函数的代码,可能影响其他依赖模块[^1]。 - **OCP的解决方案**: 定义赔付接口(如`CompensationStrategy`),新增现金赔付类实现接口,原有代码无需修改,仅需切换策略。 ```java // OCP示例:通过接口扩展 interface CompensationStrategy { void compensate(); } class CouponCompensation implements CompensationStrategy { public void compensate() { /* 代金券赔付逻辑 */ } } class CashCompensation implements CompensationStrategy { public void compensate() { /* 现金赔付逻辑 */ } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Jeff_ROS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值