简体   繁体   English

C:您如何模拟“实例”?

[英]C : How do you simulate an 'instance'?

Let's say that I have the following code in C that represents a stack : 假设我在C中有以下代码代表堆栈:

#define MAX 1000

int arr[MAX];
static int counter = 0;
isstackempty()
{
    return counter <= 0;
}
void push(int n)
{
    if (counter >= MAX) {
        printf("Stack is full.  Couldn't push %d", n);
        return;
    }
    arr[counter++] = n;
}

int pop(int* n)
{
    if(isstackempty() || n == 0) {
        printf("Stack is empty\n");
        return 0;
    }
    *n = arr[--counter];
    return 1;
}

The above code is in a stack.c file and the function prototypes are in a header. 上面的代码在stack.c文件中,函数原型在标头中。


Now, coming from a C# and OO background, if I would want to separate stack s to use in my application, in an OO language I would create two instances. 现在,来自C#和OO的背景,如果我想分离stack以在我的应用程序中使用,则以OO语言创建两个实例。 But in C, how do you handle such a scenario? 但是在C语言中,您如何处理这种情况?

Say I want to use two separate stack s in my C code...with the above code, how would I go about it? 假设我想在我的C代码中使用两个单独的stack …对于上面的代码,我将如何处理?

Put the array arr inside a struct . 将数组arr放在struct

struct stack {
    int arr[MAX];
    ...
}

This struct becomes your instance. 该结构成为您的实例。 You can then declare it on the stack: 然后可以在堆栈上声明它:

struct stack mystack;

or on the heap using malloc : 或使用malloc在堆上:

struct stack *mystack = malloc(sizeof(struct stack));

You also need to pass a pointer to the instance as the first parameter to any function manipulating the instance. 您还需要将指向该实例的指针作为操作该实例的任何函数的第一个参数传递。

The C way to do this is to wrap up all the state for your 'object' into a struct, and then explicitly pass it into all the functions that operate on stacks, so it should be: C的方法是将“对象”的所有状态包装到一个结构中,然后将其显式传递给所有在堆栈上操作的函数,因此应为:

typedef struct _stack {
  int arr[MAX];
  int counter;
} stack;

int isstackempty(stack *s)
{
    return s->counter <= 0;
}

int push(stack *s, int n)
{
    if (s->counter >= MAX) {
        printf("Stack is full.  Couldn't push %d", n);
        return -1;
    }
    arr[s->counter++] = n;
    return 0
}

int pop(stack *s, int *n)
{
    if(isstackempty(s) || n == 0) {
        printf("Stack is empty\n");
        return -1;
    }
    *n = arr[--s->counter];
    return 0;
}

The issue with your example is you're writing the function definitions like we have a class-based object structure, which C doesn't have. 您的示例的问题是您正在编写函数定义,就像我们有一个基于类的对象结构一样,而C语言则没有。 The easiest way to think about how it's done in C is that you're writing methods that require you to explicitly pass in the 'this' parameter. 考虑如何在C语言中完成工作的最简单方法是,您正在编写要求您显式传递“ this”参数的方法。

Also you can have the equivalent of constructors and destructors, which can further abstract your 'object'. 您也可以使用等效的构造函数和析构函数,从而可以进一步抽象“对象”。

stack* newStack() {
    stack* s = malloc(sizeof(stack));
    s->counter = 0;
    return s;
}

void freeStack(stack* s) {
    free(s);
}

One (extremely simplistic) way of going about it is to define a struct that represents a stack: 一种解决方法(极其简单)是定义一个表示堆栈的结构:

typedef struct {
    int arr[MAX];
    int counter = 0;
} myStack;

and then rewrite push() and pop() to operate on an instance of myStack : 然后重写push()pop()以对myStack的实例进行myStack

int push(myStack *s, int n)
{
    if (s->counter >= MAX) {
        printf("Stack is full.  Couldn't push %d", n);
        return -1;
    }
    s->arr[(s->counter)++] = n;
    return s->counter;
}

int pop(myStack *s, int* n)
{
    if(0 == s->counter || 0 == n) {
        printf("Stack is empty\n");
        return -1;
    }
    *n = s->arr[--(s->counter)];
    return 1;
}

(Also added a meaningful return value and error value to push() . YMMV.) (还向push()添加了有意义的返回值和错误值。YMMV。)

Simply make your 'this' pointer explicit: 只需使“ this”指针明确即可:

struct stack* create_stack();
void push(struct stack* mystack, int n);
void pop(struct stack* mystack, int* n);

I hope you find this paper useful. 希望本文对您有所帮助。 It gives more than one answer to your question :) 它为您的问题提供了多个答案:)

Sixteen Ways to Stack a Cat 堆猫的十六种方法

对另一个问题的回答有一个C语言中OO数据缓冲区结构的完整工作示例。

A dynamically allocated structre-per-instance is the right way to go. 动态分配每实例structre是正确的方法。 A point of detail - if you are writing a more generally used API it is probably a good idea to engage in data hiding for better abstraction. 详细点-如果您正在编写更常用的API,则最好进行数据隐藏以更好地抽象。 The simplest way of doing this is keep the definition of the internal structure in the C file (or a private header file), and typedef a void pointer to (eg) ' stack_handle_t '. 最简单的方法是将内部结构的定义保留在C文件(或专用头文件)中,并为(例如)“ stack_handle_t ”的void指针typedef。 It is this type that is returned from your 'constructor' and is passed back in to each other function. 从您的“构造函数”返回的就是这种类型,并传递回彼此的其他函数中。 The implementation is aware that the value of the handle is in fact a pointer to a structure and at the beginning of each function simply does: 该实现意识到,句柄的值实际上是指向结构的指针,并且在每个函数的开头只是执行以下操作:

int pop(stack_handle_t handle, int* n)
{
    stack *p_stack = (stack *)handle;
    ...

Even better than that is to use an internally allocated identifier instead, whether this is an index into an array of these structs or simply an identifier which can be matched against one of a (linked?) list of structs. 比这更好的是使用内部分配的标识符,而不管这是这些结构的数组的索引,还是仅仅是可以与(链接的)结构列表之一匹配的标识符。 Obviously all this is irrelevant if its only for use internal to your project, in those circumstances it is just making unnecessary work and over-complication. 显然,如果仅将其用于您的项目内部,那么所有这些都是无关紧要的,在这种情况下,这仅仅是在进行不必要的工作和过度复杂化。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM