Как упоминалось в комментариях JS1, на самом деле это довольно бессмысленно делать с примером, который у вас есть, поскольку вы не достигаете ничего с косвенностью, если вы не собираетесь изменять значение этих указателей.
Это пример использования стека (потому что логика проще, чем очередь, и это простой пример). Обратите внимание, что вы должны передать указатель на стек каждой из своих функций-членов, потому что в то время как функции-члены C++ имеют неявный аргумент this
, функции C никогда не выполняются. Вы также должны указать свое имя struct
, иначе вы не сможете обратиться к нему в реферате, который вам нужно сделать.
Эта программа использует тот же struct
реализовать два варианта стека, один нормальный один, и тот, который излишне кричит на вас, когда вы нажимаете или поп:
#include <stdio.h>
#include <stdlib.h>
enum {
STACKSIZE = 1024
};
struct stack {
int stack[STACKSIZE];
size_t top;
void (*push)(struct stack *, int);
int (*pop)(struct stack *);
void (*destroy)(struct stack *);
};
void stack_push(struct stack * this, int i)
{
if (this->top == STACKSIZE) {
fprintf(stderr, "Queue full!\n");
exit(EXIT_FAILURE);
}
this->stack[this->top++] = i;
}
void stack_push_verbose(struct stack * this, int i)
{
stack_push(this, i);
printf("** PUSHING %d ONTO STACK! **\n", i);
}
int stack_pop(struct stack * this)
{
if (this->top == 0) {
fprintf(stderr, "Stack empty!\n");
exit(EXIT_FAILURE);
}
return this->stack[--this->top];
}
int stack_pop_verbose(struct stack * this)
{
const int n = stack_pop(this);
printf("** POPPING %d FROM STACK! **\n", n);
return n;
}
void stack_destroy(struct stack * this)
{
free(this);
}
struct stack * stack_create(void)
{
struct stack * new_stack = malloc(sizeof * new_stack);
if (!new_stack) {
perror("Couldn't allocate memory");
exit(EXIT_FAILURE);
}
new_stack->top = 0;
new_stack->push = stack_push;
new_stack->pop = stack_pop;
new_stack->destroy = stack_destroy;
return new_stack;
}
struct stack * stack_verbose_create(void)
{
struct stack * new_stack = stack_create();
new_stack->push = stack_push_verbose;
new_stack->pop = stack_pop_verbose;
return new_stack;
}
int main(void)
{
struct stack * stack1 = stack_create();
struct stack * stack2 = stack_verbose_create();
stack1->push(stack1, 4);
stack1->push(stack1, 3);
stack1->push(stack1, 2);
printf("Popped from stack1: %d\n", stack1->pop(stack1));
stack2->push(stack2, 5);
stack2->push(stack2, 6);
printf("Popped from stack2: %d\n", stack2->pop(stack2));
printf("Popped from stack1: %d\n", stack1->pop(stack1));
printf("Popped from stack1: %d\n", stack1->pop(stack1));
printf("Popped from stack2: %d\n", stack2->pop(stack2));
stack1->destroy(stack1);
stack2->destroy(stack2);
return 0;
}
с выходом:
[email protected]:~/src/sandbox$ ./stack
Popped from stack1: 2
** PUSHING 5 ONTO STACK! **
** PUSHING 6 ONTO STACK! **
** POPPING 6 FROM STACK! **
Popped from stack2: 6
Popped from stack1: 3
Popped from stack1: 4
** POPPING 5 FROM STACK! **
Popped from stack2: 5
[email protected]:~/src/sandbox$
Обратите внимание, что мы используем то же самое struct stack
для обоих типов стека - различия между ними реализуются путем указания указателей функций на разные функции в каждом случае. Единственное видимое отличие от пользователя заключается в том, что он создан с stack_create()
, а другой - с stack_create_verbose()
. Во всех других отношениях они используются одинаково, поэтому вы можете увидеть полиморфизм на работе.
Я не уверен, что вы действительно спрашиваете, не могли бы вы уточнить свой вопрос? –
Вы должны объявить функции, прежде чем сможете их использовать. Вы не можете создавать инициализаторы в теле определения структуры. Используя стандарт C, вы не можете использовать количество повторов для инициализаторов, что является неприятностью. GCC предоставляет нестандартное расширение для поддержки повторных инициализаторов. –
Вы должны использовать '(void)' для функции без аргументов; в C пустой список аргументов не формирует прототип, это означает, что любое количество параметров может соответствовать (и вызывать неопределенное поведение во время выполнения). –