尽管该主题询问有关交换功能的问题,但您实际上想模仿交换功能swizzle
。这只是意味着您希望能够调用相同的函数名称,但让它做一些不同的事情。
仅指针的解决方案不会给您这种行为。如果这对您来说不重要,那么您应该采用仅提供的函数指针解决方案之一。如果它对您很重要,那么您将需要引入一个抽象层。抽象可以在底层使用函数指针(尽管还有其他解决方案)。
此接口用户的 API 将是:
/* API to initialize */
void abstract_func_init ();
/* API to manipulate abstract functions */
typedef int abstract_func_type ();
abstract_func_type * abstract_func_get (abstract_func_type *key);
int abstract_func_set (abstract_func_type *key, abstract_func_type *behavior);
/* the abstract functions */
extern int foo ();
extern int bar ();
这种接口的实现可能如下所示:
static void insert (abstract_func_type *key, abstract_func_type **behavior)
{ /* associate key to behavior */ }
static abstract_func_type ** lookup (abstract_func_type *key)
{ /* return behavior from key */ }
abstract_func_type * abstract_func_get (abstract_func_type *k) {
abstract_func_type **f = lookup(k);
if (f) return *f;
return 0;
}
int abstract_func_set (abstract_func_type *k, abstract_func_type *p) {
abstract_func_type **f = lookup(k);
if (f) {
*f = p;
return 0;
}
return -ENOENT;
}
#define DEFINE_ABSTRACT_FUNC(func) \
static int static_##func (); \
static abstract_func_type *func##_ptr = static_##func; \
int func () { return func##_ptr(); } \
static int static_##func ()
DEFINE_ABSTRACT_FUNC(foo) { return puts("foo"); }
DEFINE_ABSTRACT_FUNC(bar) { return puts("bar"); }
void abstract_func_init () {
insert(foo, &foo_ptr);
insert(bar, &bar_ptr);
}
然后,swap()
您最初在帖子中提出的内容可以这样实现:
void swap (abstract_func_type *a, abstract_func_type *b) {
abstract_func_type *ap = abstract_func_get(a);
abstract_func_type *bp = abstract_func_get(b);
abstract_func_set(a, bp);
abstract_func_set(b, ap);
}
这是一个调用的程序swap()
:
puts("before swap");
foo();
bar();
swap(foo, bar);
puts("after swap");
foo();
bar();
它的输出是:
before swap
foo
bar
after swap
bar
foo
为了自动将抽象函数添加到查找表中,您可以在构建系统中引入一个额外的步骤,该步骤调用一个脚本,该脚本会grep
输出行,并生成一个新的源文件,该文件具有一个函数,每个这样的行都有DEFINE_ABSTRACT_FUNC
调用insert()
.
可以在此处找到模型的完整版本。