用c实现C++类(八股)

news/2025/1/13 1:07:07/

在 C 语言中,虽然没有内建的面向对象编程(OOP)特性(如封装、继承、多态),但通过一些编程技巧,我们仍然可以模拟实现这些概念。下面将用通俗易懂的方式,逐步介绍如何在 C 中实现封装、继承和多态。

1. 封装(Encapsulation)

封装是指将数据和操作数据的函数绑定在一起,隐藏内部实现细节,只暴露必要的接口。在 C 中,我们可以通过 struct 和相关的函数来实现封装。

假设我们要创建一个“矩形”对象,包含宽度和高度,并提供计算面积的功能。

步骤:

  1. 定义结构体(隐藏内部细节)
  2. 提供创建和操作该结构体的函数

实现:

// Rectangle.h
#ifndef RECTANGLE_H
#define RECTANGLE_Htypedef struct Rectangle Rectangle;// 创建矩形
Rectangle* Rectangle_create(double width, double height);// 销毁矩形
void Rectangle_destroy(Rectangle* rect);// 计算面积
double Rectangle_getArea(const Rectangle* rect);#endif // RECTANGLE_H// Rectangle.c
#include <stdlib.h>
#include "Rectangle.h"// 定义结构体(隐藏在 .c 文件中)
struct Rectangle {double width;double height;
};// 创建矩形
Rectangle* Rectangle_create(double width, double height) {Rectangle* rect = (Rectangle*)malloc(sizeof(Rectangle));if (rect != NULL) {rect->width = width;rect->height = height;}return rect;
}// 销毁矩形
void Rectangle_destroy(Rectangle* rect) {free(rect);
}// 计算面积
double Rectangle_getArea(const Rectangle* rect) {if (rect == NULL) return 0.0;return rect->width * rect->height;
}// main.c
#include <stdio.h>
#include "Rectangle.h"int main() {Rectangle* rect = Rectangle_create(5.0, 3.0);if (rect != NULL) {printf("面积: %.2f\n", Rectangle_getArea(rect));Rectangle_destroy(rect);}return 0;
}

说明:

  • 隐藏实现Rectangle 的具体结构体定义在 Rectangle.c 中,外部无法直接访问其成员变量。
  • 接口函数:通过 Rectangle_createRectangle_destroyRectangle_getArea 提供对 Rectangle 对象的操作。

2. 继承(Inheritance)

继承允许一个“子类”拥有“父类”的属性和行为。在 C 中,我们可以通过在子结构体中包含父结构体来模拟继承。

基类“形状”和子类“矩形”和“圆形”

步骤:

  1. 定义基类结构体,包含一个指向函数的指针(模拟虚函数表)。
  2. 定义子类结构体,在其中包含基类结构体。
  3. 实现子类的功能

实现:

// Shape.h
#ifndef SHAPE_H
#define SHAPE_Htypedef struct Shape Shape;// 虚函数表
typedef struct {double (*getArea)(const Shape* self);void (*destroy)(Shape* self);
} ShapeVTable;// 基类结构体
struct Shape {ShapeVTable* vtable;
};// 基类接口函数
double Shape_getArea(const Shape* self);
void Shape_destroy(Shape* self);#endif // SHAPE_H// Shape.c
#include "Shape.h"double Shape_getArea(const Shape* self) {if (self && self->vtable && self->vtable->getArea) {return self->vtable->getArea(self);}return 0.0;
}void Shape_destroy(Shape* self) {if (self && self->vtable && self->vtable->destroy) {self->vtable->destroy(self);}
}// Rectangle.h
#ifndef RECTANGLE_H
#define RECTANGLE_H#include "Shape.h"typedef struct {Shape base; // 继承自 Shapedouble width;double height;
} Rectangle;// 创建矩形
Shape* Rectangle_create(double width, double height);#endif // RECTANGLE_H// Rectangle.c
#include <stdlib.h>
#include "Rectangle.h"// 矩形的虚函数实现
double Rectangle_getArea(const Shape* self) {const Rectangle* rect = (const Rectangle*)self;return rect->width * rect->height;
}void Rectangle_destroy_impl(Shape* self) {free(self);
}// 定义矩形的虚函数表
ShapeVTable rectangle_vtable = {.getArea = Rectangle_getArea,.destroy = Rectangle_destroy_impl
};// 创建矩形
Shape* Rectangle_create(double width, double height) {Rectangle* rect = (Rectangle*)malloc(sizeof(Rectangle));if (rect != NULL) {rect->base.vtable = &rectangle_vtable;rect->width = width;rect->height = height;}return (Shape*)rect;
}// Circle.h
#ifndef CIRCLE_H
#define CIRCLE_H#include "Shape.h"typedef struct {Shape base; // 继承自 Shapedouble radius;
} Circle;// 创建圆形
Shape* Circle_create(double radius);#endif // CIRCLE_H// Circle.c
#include <stdlib.h>
#include "Circle.h"
#include <math.h>// 圆形的虚函数实现
double Circle_getArea(const Shape* self) {const Circle* circle = (const Circle*)self;return M_PI * circle->radius * circle->radius;
}void Circle_destroy_impl(Shape* self) {free(self);
}// 定义圆形的虚函数表
ShapeVTable circle_vtable = {.getArea = Circle_getArea,.destroy = Circle_destroy_impl
};// 创建圆形
Shape* Circle_create(double radius) {Circle* circle = (Circle*)malloc(sizeof(Circle));if (circle != NULL) {circle->base.vtable = &circle_vtable;circle->radius = radius;}return (Shape*)circle;
}// main.c
#include <stdio.h>
#include "Shape.h"
#include "Rectangle.h"
#include "Circle.h"int main() {Shape* shapes[2];shapes[0] = Rectangle_create(5.0, 3.0); // 创建矩形shapes[1] = Circle_create(2.0);         // 创建圆形for (int i = 0; i < 2; ++i) {printf("图形 %d 的面积: %.2f\n", i + 1, Shape_getArea(shapes[i]));Shape_destroy(shapes[i]);}return 0;
}

说明:

  • 基类 Shape:包含一个虚函数表 vtable,用于指向具体实现的函数。
  • 子类 RectangleCircle
    • 包含 Shape 作为第一个成员,实现“继承”。
    • 定义自己的虚函数(如 getAreadestroy_impl)。
    • 分别创建自己的虚函数表,并在创建时将 vtable 指向自己的表。
  • 多态:在 main 中,通过基类指针 Shape* 调用 getArea,根据实际对象类型(矩形或圆形)执行不同的函数。

3. 多态(Polymorphism)

多态允许不同类型的对象通过相同的接口调用不同的实现。在上面的继承示例中,我们已经部分实现了多态。下面进一步解释多态的实现。

Shape 基类中定义了虚函数表 ShapeVTable,包含 getAreadestroy 函数指针。每个子类(如 RectangleCircle)都提供了自己的实现,并在创建时将 vtable 指向自己的函数表。

如何工作:

  1. 统一接口:所有形状都通过 Shape* 指针进行操作。
  2. 具体实现:不同的形状(矩形、圆形)有各自的 getArea 实现。
  3. 调用时自动选择:根据对象的实际类型,调用相应的 getArea 函数。

示例解释:

for (int i = 0; i < 2; ++i) {printf("图形 %d 的面积: %.2f\n", i + 1, Shape_getArea(shapes[i]));Shape_destroy(shapes[i]);
}
  • Shape_getArea(shapes[i]) 会根据 shapes[i]vtable 指向不同的 getArea 实现,自动计算出矩形或圆形的面积。

http://www.ppmy.cn/news/1562662.html

相关文章

C#中简单Socket编程

引言 Socket编程是网络编程的基础&#xff0c;通过Socket编程&#xff0c;可以实现计算机之间的通信。本文将介绍如何在C#中进行简单的Socket编程&#xff0c;包括服务器端和客户端的实现。示例将展示TCP连接的基本操作&#xff0c;适用于理解网络通信的基本概念和实现方法。 …

计算机网络——网络层-IP地址

一、IP 地址及其表示方法 • 我们把整个因特网看成为一个单一的、抽象的网络。IP 地址就是给每个连接在因特网上的主机&#xff08;或路由器&#xff09;分配一个在全世界范围是唯一的 32 位的标识符。 • IP 地址现在由因特网名字与号码指派公司ICANN (Internet Corporation f…

机器学习实战——K-均值聚类算法:原理与应用

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​​​​​​ ​​​​​​​​​​​​ ​​​​​ 1. K-均值聚类算法的原理解释 ✨ ✨ 1.1 算法概述 K-均值&#xff08;K-Means&#xff…

一分钟学会文心一言API如何接入,文心一言API接入教程

一、前期准备 注册百度智能云账号&#xff1a; 前往百度智能云官网注册一个账号。这是接入文心一言API的基础。 了解API接口&#xff1a; 在百度智能云开放平台中&#xff0c;找到文心一言API的详情页&#xff0c;了解提供的API接口类型&#xff08;如云端API、移动端API、离线…

机器学习的基本原理和算法

机器学习的基本原理是通过从数据中学习模式和规律&#xff0c;以便能够对新数据进行预测或决策。其核心思想是通过训练算法来自动地从数据中学习&#xff0c;并根据学习到的模式和规律进行预测和决策。 机器学习基本原理的深化 数据驱动&#xff1a; 机器学习依赖于大量数据来…

【Linux】Linux常见指令(上)

个人主页~ 初识Linux 一、Linux基本命令1、ls指令2、pwd命令3、cd指令4、touch指令5、mkdir指令6、rmdir指令7、rm指令8、man指令9、cp指令10、mv命令 Linux是一个开源的、稳定的、安全的、灵活的操作系统&#xff0c;Linux下的操作都是通过指令来实现的 一、Linux基本命令 先…

Python之pygame学习绘制基本图形

pygame绘制 这次来说下怎么绘制基本的图形&#xff0c;如矩形&#xff0c;圆&#xff0c;圆弧等&#xff01; pygame.draw.rect 画一个矩形 pygame.draw.polygon 绘制一个多边形 pygame.draw.circle 画一个圆圈 pygame.draw.ellipse 绘制一个椭圆 pygame.draw.arc 画…

为什么Agent会失败?2025年对AI的预测

如果说2024年是生成型人工智能的年份&#xff0c;那么2025年就应该是设定合理期望的一年。 根据科技行业分析师的预测&#xff0c;2024年本应是生成式AI&#xff08;Generative AI&#xff0c;简称GenAI&#xff09;的里程碑之年。随着各种复杂应用场景的不断涌现&#xff0c;新…