学习了Java和C++后,我学会了OO方式.我想开始一个相当雄心勃勃的项目,但我想用C语言做.我知道如何将问题分解为类以及如何将它们转换为类层次结构.我知道如何将功能抽象为抽象类和接口.我甚至有点精通以有效的方式使用多态.
问题在于,当我遇到问题时,我只知道如何做到这一点是以面向对象的方式.我变得过于依赖面向对象的设计理念和方法.
我想学习如何以严格的程序方式思考.如何在缺少类,接口,多态,函数重载,构造函数等的世界中做事情.
如何仅使用非面向对象的structs 表示复杂概念?你如何避免缺乏函数重载?以程序方式思考的一些提示和技巧是什么?
我特别感兴趣的是在C语言中使用的对象,而不是构成解释语言核心的对象的实现,例如python.
我知道原则上可以将C或MATLAB等过程语言转换为面向对象的语言.这个问题在这里和这里都得到了很好的讨论.
我在这些讨论及其中的参考文献中找不到的是对是否应该应用这些原则的说明.这样做有什么具体的东西可以获得吗?这显然是可能的,但建议这样做吗?开源项目中是否有任何例子,这种做法带来了明显的优势?
澄清
也许一个例子是有序的.
我继承了一些实现一些机器学习算法的MATLAB代码.building_model根据传递的标志,基本上只有一个函数可以训练模型或使用它来预测未来值:
building_model('train', ...) % ... stands for the data with which the model is trained
Run Code Online (Sandbox Code Playgroud)
和
value = building_model('predict')
Run Code Online (Sandbox Code Playgroud)
模型本身是用MATLAB持久变量实现的building_model.
我已经building_model分成两个功能,一个用于训练,一个用于预测.以前用作持久变量的模型现在被外部化了,可以这么说:
model = new_model()
model = model_train(model, ...)
prediction = model_predict(model)
Run Code Online (Sandbox Code Playgroud)
粗略地说,就我可以在MATLAB中管理模拟OOP的某些功能而言.我的建筑模型模块现任很像一类,有一个构造函数和两个方法model_train和model_predict.我已经实现了一定程度的封装(虽然没有什么可以阻止调用者摆弄内部的内容model),并且原则上也可以容纳多态性.作为额外的奖励,我几乎免费获得命令/查询分离,因为model_predict不返回model,因此可能不会改变model.
(精明的读者会指出MATLAB已经有一个面向对象的系统.由于各种原因,包括性能和与旧版本的兼容性,我不能使用它.)
我可以想象在C中有一个类似的机制,你可以设计一些数据结构和编写函数,其第一个参数是该数据结构的一个实例.
我想知道的是,我可以在多大程度上推动这种编程方式?这是一种普遍接受的模式(在那里,我说过这个词)?我应该注意哪些性能问题?
language-agnostic oop paradigms design-patterns design-principles
我正在用C语言设计一个操作几何图形的程序,如果每种类型的图形都可以被相同的图元操纵,那将是非常方便的.
我怎么能在C中这样做?
我对数据抽象的理解是隐藏用户的技术细节并仅显示必要的细节.因此,数据抽象是一种OOP功能.我的问题是:C是否也支持数据抽象?
如果是这样,为什么数据抽象是面向对象的编程语言特性而不是过程语言特性?
如果我的问题的答案是否定的,那么C中的结构,枚举呢?他们还隐藏了用户的详细信息.
我正在尝试设计一个可以在 Python 中轻松扩展的 C 接口(使用ctypes)。我在 C 中使用了自然习语:
struct format {
int (*can_open)(const char *filename);
struct format * (*open)(const char *filename);
void (*delete)(struct format *self);
int (*read)(struct format *self, char *buf, size_t len);
};
Run Code Online (Sandbox Code Playgroud)
如果我想直接从 C 扩展这个接口,它工作得很好:
struct derived /* concrete implementation */
{
struct format base;
};
Run Code Online (Sandbox Code Playgroud)
但我真正想做的是使用 ctypes 从 Python 实现这个接口。这是我到目前为止所拥有的:
CANOPENFUNC = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_char_p)
#OPENFUNC = ctypes.CFUNCTYPE(ctypes.c_void_p, ctypes.c_char_p)
#OPENFUNC = ctypes.CFUNCTYPE(ctypes.POINTER( python_format ), ctypes.c_char_p)
#DELETEFUNC = ctypes.CFUNCTYPE(None, ctypes.c_void_p)
#READFUNC = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_void_p)
def py_canopen_func( …Run Code Online (Sandbox Code Playgroud) 是否可以在纯ANSI-C中复制通用数组?
我有这个结构,它包含一个数组(目前用于浮点数)和一些变量,如数组中的变异大小和容量.
typedef struct _CustomArray
{
float* array; //the array in which the objects will be stored
int size; //the current size of the array
int capacity; //the max capacity of the array
} CustomArray;
Run Code Online (Sandbox Code Playgroud)
我使用这个结构,所以我可以在纯C中创建一个数组,我可以在其中添加/删除项目,在需要时动态扩展数组大小等所有"标准"数组所做的事情,除了它只用C制作.现在我想这样做,这样当你初始化这个结构时,你可以设置它应该保存的元素的数据类型,此时它只能存储浮点数据类型,但我想使它能够存储任何数据类型/其他结构.但我不知道这是否可行.
此时制作此数组的函数是:
CustomArray* CustomArray_Create(int initCapacity, /*type elementType*/)
{
CustomArray* customArray_ptr; //create pointer to point at the structure
float* internalArray = (float*)malloc(sizeof(float) * initCapacity); //create the internal array that holds the items
if(internalArray != NULL)
{
CustomArray customArray = { internalArray, 0, initCapacity }; //make the …Run Code Online (Sandbox Code Playgroud) 在下面的片段中struct IndexError,当用户使用我的库出错时,我将返回一个片段。我有一个类似于函数的宏,该宏将指针转换为IndexError*,而一个枚举都称为INDEX_ERROR。
enum errors {
SUCCESS,
INVALID_ARGUMENT,
INDEX_ERROR
};
struct Error {
char error_buff[BUFSIZ];
};
typedef struct Error Error;
struct IndexError {
Error parent;
size_t invalid_index;
// etc.
};
typedef struct IndexError IndexError;
#define INDEX_ERROR(obj) ((IndexError*) obj)
Run Code Online (Sandbox Code Playgroud)
我将如何使用此示例:
size_t pos = 4;
int IndexPointer* error = NULL;
int status = array_remove_item(my_array, pos, &error);
Run Code Online (Sandbox Code Playgroud)
然后,我检查状态。如果它没有返回SUCCESS,我将检查该错误,因为那应该指向一个新创建的错误。
数组函数之一的实现可能如下所示:
int array_remove_item(Array* array, size_t pos, Error** error_out)
{
Error* error = NULL;
if(pos >= array->size) {
index_error_create(INDEX_ERROR(&error), …Run Code Online (Sandbox Code Playgroud)