我想知道如何解决包装问题 Stroustrup paper但是在C.我正试图找到一种有效的方式来调用
// prefix
GenericFunctionCallThatCouldHaveAnyNumberOfArgs();
// suffix
我考虑过创建一个代理函数,它接受一个输入函数指针,但我想要包装的函数并不都具有相同的函数签名。
我目前的解决方案是创建一个宏:
#define CALL(func) prefix; func; suffix;
CALL(myfunction(a, 'b', 1))
它有效,但它使代码更难理解,特别是当前缀和后缀很复杂时。前缀和后缀也不一定是对函数的调用,它们也可以是封装。在C中是否有一种设计模式能够有效地(在代码行方面)实现这一点,同时仍然保持可读性。
答案 0 :(得分:1)
对于返回类型void
的函数调用,您可以使用comma operator,它有一些限制 - 允许指定一个接一个地计算的表达式,包括函数调用。
例如,你可以写
#define prefix printf("something in prefix\n")
#define suffix printf("something as suffix\n")
void someFunction(int x) {
printf("some function, parameter value %d\n", x);
}
#define CALL(func) (prefix,func,suffix)
int main() {
CALL(someFunction(10));
}
输出:
something in prefix
some function, parameter value 10
something as suffix
在逗号运算符中使用的表达式有几个限制。例如,您无法在此类表达式的过程中定义变量。但是,有一些策略可以克服这个问题,例如:通过引入全局变量或通过调用函数(当然可以定义局部变量)。
返回类型void
的原因是你想要在中间调用你的函数,即不是逗号运算符中的最后一个表达式,但是逗号运算符per的结果总是值最后一个表达式计算的结果。请进一步注意,使用#define CALL(func)
- 方法prefix
或suffix
中的任何更改都需要重新编译您的程序。但我认为无论如何你都知道这一点。
希望它有所帮助。
答案 1 :(得分:1)
我考虑过创建一个代理函数,它接受一个输入函数指针,但我想要包装的函数并不都具有相同的函数签名。
这可以通过添加另一层间接来解决。但是,它不会使代码更短。
假设我们想要使用相同的前缀/后缀代码调用两个函数foo()
(不传递参数)和bar(42, "hello")
(两个不同类型的参数)。
我们可以这样做:
void call_decorated(void (*f)(void *), void *p) {
printf("prefix code\n");
f(p);
printf("suffix code\n");
}
这允许我们调用任何带有单个void *
参数的函数。要在foo
和bar
中使用它,我们必须编写适配器函数:
void wrap_foo(void *p) {
foo();
}
struct bar_args {
int n;
const char *s;
};
void wrap_bar(void *p) {
struct bar_args *args = p;
bar(args->n, args->s);
}
现在我们可以这样调用call_decorated
:
call_decorated(wrap_foo, NULL);
struct bar_args args = { 42, "hello" };
call_decorated(wrap_bar, &args);
这非常繁琐,但源中只有一个前缀/后缀代码实例。