当前位置: 首页 > news >正文

c语言杂谈系列:模拟虚函数

从整体来看,笔者的做法与之前的模拟多态十分相似,毕竟c++多态的实现与虚函数密切相关

废话少说,see my code:

kernel.c#include "kernel.h"
#include <stdio.h>void shape_draw(struct shape_t* obj) {/* Call draw of the real Instance */obj->vtable->draw();}
kernel.h:#ifndef UNTITLED_KERNEL_H
#define UNTITLED_KERNEL_Hstruct shape_t {/*Virtual Method Table */const struct shape_interface* const vtable;
};struct shape_interface {void (*draw)();};void shape_draw(struct shape_t* obj);//obj->vtable->draw();#endif //UNTITLED_KERNEL_H
try.c:#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "try.h"void draw() {printf("error is try!\n");
}void draw1() {printf("error is try2!\n");
}struct shape_t* shape_create_rectangle() {//直接赋值,这里有个命名错误,跟gcc有关://static const struct shape_interface_t vtable = { draw1 } ;//static struct shape_t base = { &vtable };//笔者认为给结构体成员赋值,下面的写法更妥当static const struct shape_interface vtable = { .draw = draw1} ;static struct shape_t base = { .vtable = &vtable};//推荐上面这种写法,因为某些编译器很有趣struct rectangle_t* rectangle = malloc(sizeof(*rectangle));memcpy(&rectangle->base, &base, sizeof(base));return (struct shape_t*)(&rectangle->base);
}

顺便一提,clion的编译器相当有趣

笔者在之前曾经写错了shape_interface (_t)结构体名称,但是笔者发现:

//static const struct shape_interface_t *vtable = { draw1 } ;
//static struct shape_t base = { &vtable };

改成这样也能运行

这是为什么呢?笔者推测,gcc应该是无法找到对于结构体,就把vtable当成了数组,加上*就成为了数组。然后&vtable就成为了二级指针,由于draw1本身就是一个指针,把它转成空指针什么的可以随便赋值。gcc在找不到对应结构体后,索性为base里的vtable开辟了一段空间,由于&vatble是二级指针,但是找不到对应地址指向,可能它在编译过程中被转为了一级空指针,且等于draw1本身,这样就能解释通了。(如果有c语言高手可以留言解答一下,笔者对c语言和编译器的处理所知甚少)

try.h:#ifndef UNTITLED_TRY_H
#define UNTITLED_TRY_H#include "kernel.h"struct rectangle_t {struct shape_t* base; /* Reference to Base Class *//* Rectangle specific Members */int x;int y;
};struct shape_t* shape_create_rectangle();#endif //UNTITLED_TRY_H

在主函数中这样调用即可:

main.c:#include "try.h"
#include "kernel.h"int main() {struct shape_t* rectangle = shape_create_rectangle();shape_draw(rectangle);return 0;
}

接下来是重点,虚函数表的实现,可以适当改动try.c文件:

try.c://
// Created by el on 2024/8/16.
//#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "try.h"void draw() {printf("error is try!\n");
}void draw1() {printf("error is try2!\n");
}struct shape_t* shape_create_rectangle() {//static const struct shape_interface *vtable[] = { draw , draw1 } ;static const struct shape_interface_t *vtable[] = { .vtable = draw} ;static struct shape_t base = { vtable + 1};struct rectangle_t* rectangle = malloc(sizeof(*rectangle));memcpy(&rectangle->base, &base, sizeof(base));return (struct shape_t*)(&rectangle->base);
}

使用函数指针数组,就可以模拟出比较相近的虚函数表。

整个c程序的UML图如下:

UML

其实这张图跟笔者前一篇模拟多态的文章思想是一样的。

相关文章:

c语言杂谈系列:模拟虚函数

从整体来看&#xff0c;笔者的做法与之前的模拟多态十分相似&#xff0c;毕竟c多态的实现与虚函数密切相关 废话少说&#xff0c;see my code&#xff1a; kernel.c#include "kernel.h" #include <stdio.h>void shape_draw(struct shape_t* obj) {/* Call dr…...

短视频推广App不再难!Xinstall来帮忙

在短视频风靡的今天&#xff0c;如何利用这一热门媒介有效推广App&#xff0c;成为了许多推广者关注的焦点。而Xinstall&#xff0c;作为国内专业的App全渠道统计服务商&#xff0c;正是你解决这一难题的得力助手。 首先&#xff0c;Xinstall在数据维度上的优势无可比拟。它能…...

打靶记录13——doubletrouble

靶机&#xff1a; https://www.vulnhub.com/entry/doubletrouble-1,743/ 难度&#xff1a; 中 目标&#xff1a; 取得两台靶机 root 权限 涉及攻击方法&#xff1a; 主机发现端口扫描Web信息收集开源CMS漏洞利用隐写术密码爆破GTFObins提权SQL盲注脏牛提权 学习记录&am…...

awk文本处理工具

awk 是一个强大的文本处理工具&#xff0c;在Shell编程中常用于处理和分析文本数据。它可以按列处理数据&#xff0c;进行模式匹配&#xff0c;生成报告&#xff0c;执行计算等。以下是一些 awk 的主要功能和使用场景&#xff1a; 期待您的关注 美好的观念较美人尤为可爱 目录 …...

计算机毕业设计选题推荐-学院网站系统-Java/Python项目实战

✨作者主页&#xff1a;IT毕设梦工厂✨ 个人简介&#xff1a;曾从事计算机专业培训教学&#xff0c;擅长Java、Python、微信小程序、Golang、安卓Android等项目实战。接项目定制开发、代码讲解、答辩教学、文档编写、降重等。 ☑文末获取源码☑ 精彩专栏推荐⬇⬇⬇ Java项目 Py…...

Spring模块详解Ⅰ

目录 SpringSpring框架的主要功能模块1. Core Container&#xff08;核心容器&#xff09;2. Data Access/Integration&#xff08;数据访问与集成&#xff09;3. Web4. AOP (Aspect-Oriented Programming&#xff0c;面向切面编程)5. Instrumentation&#xff08;工具集&#…...

C语言程序设计-练习篇

山海自有归期&#xff0c;风雨自有相逢。 一 下面代码的结果是什么&#xff1f; int main() { int i 0; for (i 0; i < 10; i) { if (i 5) //此处为赋值&#xff0c;i 5表达式结果为5 printf("%d ", i); //表达式为真&a…...

【Oracle篇】统计信息和动态采样的深度剖析(第一篇,总共六篇)

&#x1f4ab;《博主介绍》&#xff1a;✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ &#x1f4ab;《擅长领域》&#xff1a;✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux&#xff0c;也在扩展大数据方向的知识面✌️…...

无源互调自动化测试软件应用案例分享:S参数和互调的高效测试

随着产品种类的丰富和市场需求的变化&#xff0c;合肥某电子技术公司意识到&#xff0c;传统的手工测试已无法满足公司持续发展的需要。于是&#xff0c;一场自动化测试转型悄然展开。 一、背景介绍 合肥某电子技术公司成立于2009年&#xff0c;专注于功分器、耦合器、负载器、…...

【6大设计原则】精通设计模式之里氏代换原则:从理论到实践,掌握代码演化的黄金法则

一、引言 1.1 设计模式的必要性 在软件开发的复杂性面前&#xff0c;设计模式提供了一套成熟的解决方案&#xff0c;它们是经过多年实践总结出来的&#xff0c;能够帮助我们应对各种编程难题。设计模式不仅仅是一种编程技巧&#xff0c;更是一种编程哲学&#xff0c;它能够提…...

国内服务器安装Docker提示Failed to connect to download.docker.com port 443的解决方案

解决方案 换国内镜像源。我用的是清华的。https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ 自己找自己对应的版本。 例如你的Ubuntu系统。就用下列命令 sudo curl -fsSL https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/ubuntu/gpg -o /etc/apt/keyrings/do…...

前端开发攻略---彻底弄懂跨域解决方案

目录 1、浏览器的同源策略 1.1 源 1.2 同源与非同源 1.3 同源请求与非同源请求 2、跨域受到的限制 3、注意点 4、CORS解决Ajax跨域问题 4.1 CORS概述 4.2 CORS解决简单请求跨域 4.3 简单请求与复杂请求 4.4 CORS解决复杂请求跨域 4.5 借助CORS库快速完成配置 5、JS…...

【HeadFirst 设计模式】装饰者模式的C++实现

一、案例背景 Starbuzz是以扩张速度最快而闻名的咖啡连锁店。如果你在街角看到它的店&#xff0c;在对面街上肯定还会看到另一家。因为扩张速度实在太快了&#xff0c;他们准备更新订单系统&#xff0c;以合乎他们的饮料供应要求。他们原先的类设计是这样的…… 购买咖啡时&am…...

大白话解释TCP的三次握手和四次挥手

你好&#xff0c;我是沐爸&#xff0c;欢迎点赞、收藏和关注。个人知乎 TCP的三次握手是浏览器与服务器建立连接的过程&#xff0c;而四次挥手&#xff0c;是两者断开连接的过程。今天把客户端和服务端当做两个人&#xff0c;通过打电话的方式解释连接建立和断开的过程。 TCP…...

asyncua模块实现OPC UA通讯

asyncua是OPCUA的python实现&#xff0c;使用起来非常方便&#xff0c;其github地址是https://github.com/FreeOpcUa/opcua-asyncio UaExpert是OPC UA Client的GUI工具&#xff0c;当编写好server代码后并运行&#xff0c;我们可以使用UaExpert去和server进行通信。UaExpert使…...

RabbitMQ的核心概念

RabbitMQ是一个消息中间件&#xff0c;也是一个生产者消费者模型&#xff0c;负责接收&#xff0c;存储和转发消息。 核心概念 Producer 生产者&#xff0c;是RabbitMQ Server的客户端&#xff0c;向RabbitMQ发送消息。 Consumer 消费者&#xff0c;是RabbitMQ Server的客…...

【vSphere 7/8】深入浅出 vSphere 证书 Ⅰ—— 初识和了解 vSphere证书

目录 摘要1. vSphere 安全证书1.1 vSphere 安全证书的类型和有效期 2. 在 vSphere Client 中初识 vSphere 证书2.1 vCenter 8.0.3 的 vSphere Client 界面2.2 vCenter Server 7.0 Update2 到 vCenter Server 8.0 Update 2 的 vSphere Client 界面2.3 vCenter Server 7.0 到 vCe…...

【云备份】服务端模块-热点管理

文章目录 0.回顾extern1.介绍2.实现思想3.代码测试代码 热点管理总结 0.回顾extern extern cloudBackup::DataManager *_dataManager extern 关键字用于声明一个全局变量或对象&#xff0c;而不定义它。这意味着 _dataManager 是一个指向 cloudBackup::DataManager 类型的指针…...

call apply bind特性及手动实现

call // 原生的call var foo { value: 1 };function bar(...args) {console.log("this", this.value, args); }bar.call(foo)// call 改变了bar的this指向 // bar函数执行了 // 等价于 // var foo { // name: "tengzhu", // sex: "man", …...

pygame开发课程系列(5): 游戏逻辑

第五章 游戏逻辑 在本章中&#xff0c;我们将探讨游戏开发中的核心逻辑&#xff0c;包括碰撞检测、分数系统和游戏状态管理。这些元素不仅是游戏功能的关键&#xff0c;还能显著提升游戏的趣味性和挑战性。 5.1 碰撞检测 碰撞检测是游戏开发中的一个重要方面&#xff0c;它用…...

使用mcp-maker快速构建AI工具调用服务器:从协议原理到工程实践

1. 项目概述与核心价值最近在折腾AI应用开发&#xff0c;特别是想给大语言模型&#xff08;LLM&#xff09;装上更强大的“手脚”&#xff0c;让它能直接操作我电脑上的各种软件和工具。这听起来很酷&#xff0c;对吧&#xff1f;但实际操作起来&#xff0c;你会发现一个核心痛…...

基于MCP协议的AI Agent远程SSH安全操作实践指南

1. 项目概述与核心价值最近在折腾AI Agent的开发&#xff0c;发现一个挺有意思的现象&#xff1a;很多开发者都卡在了“如何让AI安全、可控地操作远程服务器”这一步。你可能会想到直接给AI一个SSH私钥&#xff0c;但这无异于把自家大门的钥匙扔给一个还在学习走路的机器人&…...

基于RP2040与I2C总线打造可编程合成器吉他:从硬件到固件的完整实践

1. 项目概述&#xff1a;打造你的第一把可编程合成器吉他 如果你对电子音乐制作和嵌入式硬件开发都感兴趣&#xff0c;那么将两者结合的DIY项目无疑是最迷人的领域。今天要分享的&#xff0c;就是基于Adafruit RP2040 PropMaker Feather微控制器&#xff0c;从零开始打造一把功…...

从二维到三维:DIY LED视频立方体构建全攻略

1. 项目概述&#xff1a;从平面到立体的视觉革命几年前&#xff0c;当我第一次成功点亮一整面由32x32 RGB LED面板组成的视频墙时&#xff0c;那种由1024个像素点共同编织出的动态画面所带来的震撼&#xff0c;至今记忆犹新。但作为一个热衷于将技术推向边界的创作者&#xff0…...

Cursor与Figma通过MCP协议实现AI辅助设计与开发同步

1. 项目概述&#xff1a;当代码编辑器与设计工具“开口说话”最近在开发者社区里&#xff0c;一个名为“cursor-talk-to-figma-mcp”的项目引起了我的注意。这个由开发者“hamadoun1760”开源的仓库&#xff0c;名字直译过来就是“Cursor与Figma对话的MCP”。乍一看&#xff0c…...

从零构建Next.js全栈应用:实战解析服务端渲染与API路由

1. 项目概述与核心价值最近在社区里看到不少朋友在讨论一个叫“panaverse/learn-nextjs”的项目&#xff0c;作为一个在Web开发领域摸爬滚打了十多年的老码农&#xff0c;我立刻来了兴趣。这个项目名直译过来就是“Panaverse的Next.js学习项目”&#xff0c;听起来像是一个学习…...

FPGA与GPU在OSOS-ELM算法中的性能对比与优化

1. 项目概述在边缘计算和实时信号处理领域&#xff0c;极端学习机(ELM)因其独特的训练机制和高效的计算性能而备受关注。OSOS-ELM作为ELM的一种变体&#xff0c;通过在线顺序学习机制进一步提升了算法的实用性。这项研究聚焦于FPGA和GPU两种硬件平台在执行OSOS-ELM算法时的性能…...

Carapace:统一跨Shell命令行补全的Go语言引擎

1. 项目概述&#xff1a;一个为Shell而生的全能补全引擎 如果你和我一样&#xff0c;每天有超过一半的工作时间是在终端里度过的&#xff0c;那你一定对命令行补全这件事又爱又恨。爱的是&#xff0c;一个恰到好处的补全能让你行云流水&#xff0c;效率倍增&#xff1b;恨的是…...

汽车该多久换一代

汽车该多久换一代 买车的人其实不怕四年换代&#xff0c;怕的是刚提车半年就被新款打成旧款。李想这句话能引起讨论&#xff0c;原因也在这里&#xff1a;车企说的是研发验证周期&#xff0c;车主感受到的是价格、配置和二手残值。 汽车确实没法完全照着手机节奏跑。手机坏了可…...

3D打印LED发光史莱姆:零焊接电子制作与创意材料科学实践

1. 项目概述&#xff1a;当电子制作遇上创意手工几年前&#xff0c;我在一个社区创客空间带孩子们做活动&#xff0c;发现一个挺有意思的现象&#xff1a;一讲到电路、LED、电阻&#xff0c;不少孩子眼神就开始飘忽&#xff1b;但一旦拿出会发光的、可以随意揉捏的“史莱姆”泥…...