假设我必须使用 C(没有 C++ 或面向对象的编译器)并且我没有动态内存分配,我可以使用哪些技术来实现类或类的良好近似?将“类”隔离到一个单独的文件总是一个好主意吗?假设我们可以通过假设固定数量的实例来预分配内存,甚至可以在编译前将每个对象的引用定义为常量。请随意假设我需要实现哪个 OOP 概念(它会有所不同),并为每个概念提出最佳方法。
限制:
- 我必须使用 C 而不是 OOP
因为我正在为一个
嵌入式系统,以及编译器和
预先存在的代码库是 C 语言。
- 没有动态内存分配
因为我们没有足够的内存
合理地假设我们不会耗尽
如果我们开始动态分配
- 我们使用的编译器在函数指针方面没有问题
这取决于您想要拥有的确切“面向对象”功能集。如果您需要重载和/或虚拟方法之类的东西,您可能需要在结构中包含函数指针:
typedef struct {
float (*computeArea)(const ShapeClass *shape);
} ShapeClass;
float shape_computeArea(const ShapeClass *shape)
{
return shape->computeArea(shape);
}
这将使您通过“继承”基类并实现合适的功能来实现一个类:
typedef struct {
ShapeClass shape;
float width, height;
} RectangleClass;
static float rectangle_computeArea(const ShapeClass *shape)
{
const RectangleClass *rect = (const RectangleClass *) shape;
return rect->width * rect->height;
}
当然,这还需要您实现一个构造函数,以确保正确设置函数指针。通常你会为实例动态分配内存,但你也可以让调用者这样做:
void rectangle_new(RectangleClass *rect)
{
rect->width = rect->height = 0.f;
rect->shape.computeArea = rectangle_computeArea;
}
如果你想要几个不同的构造函数,你将不得不“修饰”函数名,你不能有一个以上的rectangle_new()
函数:
void rectangle_new_with_lengths(RectangleClass *rect, float width, float height)
{
rectangle_new(rect);
rect->width = width;
rect->height = height;
}
这是一个显示用法的基本示例:
int main(void)
{
RectangleClass r1;
rectangle_new_with_lengths(&r1, 4.f, 5.f);
printf("rectangle r1's area is %f units square\n", shape_computeArea(&r1));
return 0;
}
我希望这至少能给您一些想法。对于 C 中成功且丰富的面向对象框架,请查看 glib 的 GObject图书馆。
另请注意,上面没有明确的“类”建模,每个对象都有自己的方法指针,这比您通常在 C++ 中找到的要灵活一些。此外,它会消耗内存。您可以通过将方法指针填充到 class
结构中来避免这种情况,并为每个对象实例发明一种引用类的方法。