如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;
}
带有输出的:
paul@horus:~/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
paul@horus:~/src/sandbox$
请注意,我们对两种类型的堆栈使用完全相同的
struct stack
- 它们之间的差异是通过在每种情况下将函数指针指向不同的函数来实现的。对用户而言唯一可见的区别是一个使用
stack_create()
创建,另一个使用
stack_create_verbose()
创建。在所有其他方面,它们被完全相同地使用,因此您可以看到多态性的作用。
(void)
;在 C 中,空的参数列表不形成原型,这意味着任何数量的参数都可以匹配(并在运行时导致未定义的行为)。 - M.M