OOC Relation Plugin:C 语言面向对象开发的高效辅助工具

摘要:本文介绍了一款专为 C 语言 OOC(面向对象 C)开发打造的 VS Code 扩展——OOC Relation Plugin。它通过可视化继承树、一键类创建、智能虚函数管理、PlantUML 类图生成与智能文件同步等核心功能,解决了大型 C 项目中手动模拟面向对象编程时结构混乱、维护困难的问题,让 C 语言的继承、多态与接口设计变得清晰可见、高效可维护。

在嵌入式系统、操作系统内核以及大型 C 语言项目中,开发者常常使用结构体嵌套与函数指针表来模拟面向对象编程(OOC,Object-Oriented C)。然而,传统的集成开发环境对这类手动模拟的类继承、虚函数、接口等概念几乎没有支持,导致项目结构难以理解,维护成本高昂。

OOC Relation Plugin 正是为解决这一痛点而生。它是一个 VS Code 扩展,为 OOC 风格的 C 代码提供完整的类关系管理与可视化功能,让开发者像使用面向对象语言一样清晰地掌控项目中的类层次结构。


核心功能

1. 可视化继承树

插件在侧边栏提供“OOC Inheritance”视图,以树形结构直观展示所有类之间的继承关系。

  • 图标区分:普通类、接口、拥有虚表的类分别使用不同图标,一目了然。
  • 悬停详情:鼠标悬停即可查看类的文件路径、是否有虚表、父类信息等。
  • 快速导航:点击节点直接打开对应的头文件。

2. 一键创建 OOC 类

通过右键菜单或命令面板,快速创建基类、接口或子类,自动生成规范的 .h.c 文件。

创建基类

假设我们要创建一个名为 Animal 的基类,右键文件夹选择 OOC: Create Class,输入类名,插件将生成以下文件:

Animal.h

#ifndef ANIMAL_H
#define ANIMAL_H

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>

typedef struct _Animal Animal;

struct AnimalFun {
    void (*destroy)(Animal *self);
};

struct AnimalVtable {
    void (*speak)(Animal *self);
    
};

struct _Animal {
    struct AnimalVtable *vtable;
    const struct AnimalFun *fun;
    /* TODO: Add member variables here */
};

Animal *Animal_create(void);
void Animal_destroy(Animal *self);
void Animal_init(Animal *self);
void Animal_deinit(Animal *self);

extern const struct AnimalFun Animal_fun;

#endif /* ANIMAL_H */

Animal.c

#include "Animal.h"
#include <stdlib.h>
#include <string.h>
static void default_Animal_speak_impl(Animal *self);

const struct AnimalFun Animal_fun = {
    .destroy = Animal_destroy,
};

Animal *Animal_create(void) {
    Animal *self = (Animal*)malloc(sizeof(Animal));
    if (!self) return NULL;
    memset(self, 0, sizeof(Animal));
    Animal_init(self);
    return self;
}

void Animal_destroy(Animal *self) {
    if (!self) return;
    Animal_deinit(self);
    free(self);
}

void Animal_init(Animal *self) {

    /* OOC vtable allocation */
    if (!self->vtable) {
        self->vtable = (struct AnimalVtable*)malloc(sizeof(struct AnimalVtable));
        if (self->vtable) {
            memset(self->vtable, 0, sizeof(struct AnimalVtable));
        }
    }
    if (!self) return;
    self->fun = &Animal_fun;
    self->vtable->speak = default_Animal_speak_impl;
}

void Animal_deinit(Animal *self) {
    if (!self) return;
    if (self->vtable) {
        free(self->vtable);
        self->vtable = NULL;
    }
}


static void default_Animal_speak_impl(Animal *self) {
    /* TODO: Implement default behavior */
    (void)self;
    
}

创建子类

Animal.h 上右键选择 OOC: Create Subclass,输入子类名 Dog,插件会基于父类自动生成包含 union 继承和虚表指针的子类模板:

Dog.h

#ifndef DOG_H
#define DOG_H

#include "Animal.h"

typedef struct _Dog Dog;

struct DogFun {
    void (*destroy)(Dog *self);
};

struct DogVtable {
    struct AnimalVtable parent;  /* inherited from Animal */
    void (*bark)(Dog *self);
    
};

struct _Dog {
    union { Animal parent; struct DogVtable *vtable; };
    const struct DogFun *fun;
};

Dog *Dog_create(void);
void Dog_destroy(Dog *self);
void Dog_init(Dog *self);
void Dog_deinit(Dog *self);

extern const struct DogFun Dog_fun;

#endif /* DOG_H */

Dog.c

#include "Dog.h"
#include <stdlib.h>
#include <string.h>
static void override_Dog_Animal_speak_impl(Animal *self);
static void default_Dog_bark_impl(Dog *self);

const struct DogFun Dog_fun = {
    .destroy = Dog_destroy,
};

Dog *Dog_create(void) {
    Dog *self = (Dog*)malloc(sizeof(Dog));
    if (!self) return NULL;
    memset(self, 0, sizeof(Dog));
    Dog_init(self);
    return self;
}

void Dog_destroy(Dog *self) {
    if (!self) return;
    Dog_deinit(self);
    free(self);
}

void Dog_init(Dog *self) {

    /* OOC vtable allocation */
    if (!self->vtable) {
        self->vtable = (struct DogVtable*)malloc(sizeof(struct AnimalVtable));
        if (self->vtable) {
            memset(self->vtable, 0, sizeof(struct AnimalVtable));
        }
    }
    if (!self) return;
    Animal_init(&self->parent);
    self->fun = &Dog_fun;
    self->vtable->bark = default_Dog_bark_impl;
    self->parent.vtable->speak = override_Dog_Animal_speak_impl;
}

void Dog_deinit(Dog *self) {
    if (!self) return;
    Animal_deinit(&self->parent);
    if (self->vtable) {
        free(self->vtable);
        self->vtable = NULL;
    }
}


static void default_Dog_bark_impl(Dog *self) {
    /* TODO: Implement default behavior */
    (void)self;
    
}


static void override_Dog_Animal_speak_impl(Animal *self) {
    Dog *child = (Dog*)self;
    /* TODO: Override implementation */
    (void)child;
    
}

这种模板遵循了 OOC 的经典约定:通过 union 将父类结构体和虚表指针共用同一块内存,实现继承与多态的基础。

创建接口

接口是一种特殊的抽象类,只定义虚函数而不提供实现。通过 OOC: Create Interface 命令,可以在创建时定义虚函数签名,生成如下代码:

IAnimal.h

#ifndef IANIMAL_H
#define IANIMAL_H

#include <stdint.h>

typedef struct _IAnimal IAnimal;

struct IAnimalVtable {
    void (*speak)(IAnimal *self);
};

struct _IAnimal {
    struct IAnimalVtable *vtable;
};

void IAnimal_init(IAnimal *self);
void IAnimal_deinit(IAnimal *self);

#endif /* IANIMAL_H */

接口类的特点是:结构体只包含虚表指针,没有任何数据成员,虚表结构体则声明了纯虚函数指针。

3. 智能虚函数管理

虚函数(多态)是 OOC 的核心,也是最容易出错的部分。插件提供了完整的虚函数生命周期管理。

添加虚函数

Dog.h 上右键选择 OOC: Add Virtual Method,插件会自动检测继承链,收集所有祖先的虚函数(例如父类 Animal 若有虚表则继承其方法)。如果当前类还没有虚表,插件会自动创建虚表结构体,并向上传播占位符确保继承链完整。

在弹出的面板中,左侧列出所有已继承的虚函数,右侧可以添加新的虚方法(定义返回值、方法名、参数)。例如为 Dog 添加一个 bark 虚函数,提交后插件将自动完成以下操作:

  1. Dog.h 中插入虚表结构体定义(如果尚未存在):
struct DogVtable {
    void (*bark)(Dog *self);
    
};
  1. Dog.c 中生成默认实现函数和虚表赋值代码:
// 默认实现
static void default_Dog_bark_impl(Dog *self) {
    /* TODO: Implement default behavior */
    (void)self;
}

// 在 Dog_init 函数中自动插入虚表分配和赋值
    /* OOC vtable allocation */
    if (!self->vtable) {
        self->vtable = (struct DogVtable*)malloc(sizeof(struct DogVtable));
        if (self->vtable) {
            memset(self->vtable, 0, sizeof(struct DogVtable));
        }
    }
    if (!self) return;
    Animal_init(&self->parent);
    self->fun = &Dog_fun;
    self->vtable->bark = default_Dog_bark_impl;

如果父类还没有虚表,插件会先在父类中插入一个占位符 const void *_vtable;,保证子类的虚表能够通过 parent 成员正确链接,后续为父类添加虚函数时会自动替换为真正的虚表指针。

重写虚函数

当子类需要定制父类虚函数的行为时,使用 OOC: Override Methods。面板会列出所有祖先中已声明的虚方法,已重写的自动置灰并标记为 “already overridden”,未重写的可以勾选,一键生成覆盖函数。

例如,在 Cat 中重写从 Animal 继承的 speak 方法,插件将生成:

// 前向声明
static void override_Cat_IAnimal_speak_impl(IAnimal *self);
// 在 Cat_init 中赋值虚表
    self->parent.vtable->speak = override_Cat_IAnimal_speak_impl;
// 覆盖实现
static void override_Cat_IAnimal_speak_impl(IAnimal *self) {
    Cat *child = (Cat*)self;
    /* TODO: Override implementation */
    (void)child;
    
}

注意函数参数中包含父类类型指针,内部将 self 强制转换为子类类型以便访问子类成员,这是 OOC 惯用的手法。

4. 常规方法与成员变量管理

除了虚函数,OOC 中还有通过“Fun 表”实现的普通方法(非虚方法),以及常规的成员变量。

添加常规方法(Fun 表)

右键头文件选择 OOC: Add Regular Method,在面板中输入方法签名,插件会向类的 Fun 结构体插入函数指针声明,并在 .c 文件中生成对应的实现函数和初始化赋值。例如为 Dog 添加一个 run 方法:

生成的 Fun 结构体成员:

void (*run)(Dog *self, int speed);

生成的实现和赋值:

static void Dog_run(Dog *self, int speed) {
    /* TODO: Implement */
}

// 在 Dog_init 中
self->fun->run = Dog_run;
添加成员变量

通过 OOC: Add Members 命令,可视化面板可添加成员变量,自动插入到结构体定义末尾。支持重名检查,避免编译错误。例如为 Dog 添加 int age 成员,结构体变为:

typedef struct Dog {
    union {
        Animal parent;
        struct DogVtable *vtable;
    };
    int age;
} Dog;

5. PlantUML 类图生成

基于项目中的类关系,一键生成标准 UML 类图,帮助开发者快速理解架构或编写文档。

  • 完整展示:属性(- type name)、虚函数(标注 + {abstract} method(params))、普通方法、继承关系(<|--)、依赖(..>)、聚合(o--)一应俱全。
  • 智能接口识别:生成类图时会检查源文件中是否包含虚函数的默认实现,若没有任何实现则自动标记为 <<interface>>,并用虚线箭头表示实现关系。
  • 交互操作:支持 Ctrl+滚轮以光标为中心缩放、拖拽平移、双击重置视图。
  • 一键保存:点击工具栏的保存按钮,可将完整的 PlantUML 源码导出为 .puml 文件,方便集成到文档或持续集成流水线中。

生成的 PlantUML 示例:

@startuml
class "Animal" {
  - int age
  + {abstract} speak(Animal *self, int volume)
}

class "Dog" {
  - int age
  + {abstract} speak(Animal *self, int volume)
  + {abstract} bark(Dog *self)
  + run(Dog *self, int speed)
}

"Dog" --|> "Animal"
@enduml

6. 智能缓存与文件同步

插件的所有功能都基于一个轻量级的关系缓存文件(.vscode/class-relations.json),只记录通过插件操作过的类,启动时无需扫描整个项目,响应极快。

  • 操作即记录:每当你创建类、添加虚函数等操作,插件自动将类名、父类、文件相对路径、是否有虚表等信息记录到缓存。
  • 自动同步:当文件被移动、重命名或删除时,缓存中的路径会自动更新或移除对应条目,确保视图始终与文件系统一致。
  • 状态自修正:生成类图时会自动检测类的接口状态,如果与缓存不一致(例如原本有实现后来删除),会立即更正缓存标记,下次打开视图即可看到更新后的图标。

这个设计使得插件即使在数千个文件的大项目中也能保持极低的资源占用,完全告别全量扫描的卡顿。


命令一览

命令 说明 触发方式
OOC: Create Class 创建基类 右键文件夹 / 命令面板
OOC: Create Interface 创建接口 右键文件夹 / 命令面板
OOC: Create Subclass 创建子类 右键 .h 文件
OOC: Add Virtual Method 添加虚函数 右键 .h 文件
OOC: Add Regular Method 添加常规方法 右键 .h 文件
OOC: Override Methods 重写祖先虚函数 右键 .h 文件
OOC: Add Members 添加成员变量 右键 .h 文件
OOC: Show Class Diagram 生成 PlantUML 类图 命令面板 / 侧边栏节点

安装与使用

  1. 在 VS Code 扩展市场搜索 OOC Relation Plugin 并安装。
  2. 打开你的 C 语言项目。
  3. 通过右键菜单或命令面板开始创建类、添加虚函数。
  4. 侧边栏自动展示继承关系,随时生成类图导出文档。

适用场景

  • 嵌入式 C 项目中的 HAL 层、驱动层抽象
  • 使用 OOC 模式的大型 C 项目
  • 教学演示 C 语言面向对象编程
  • 需要生成 C 项目架构文档

OOC Relation Plugin 让 C 语言的面向对象开发不再靠想象——它让每一层继承、每一个虚表、每一个接口都清晰可见。立即安装,体验高效的结构化 C 开发!

github开源地址:

ooc-relation-plugin

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐