我不是C专家。我的CS1&大学2天。我已经在这里和那里做了一点C ++,但它已经有一段时间了。所以我要问的是正确的模式来解决我所感知的问题。
我决定接受一个相当雄心勃勃的挑战,我在C中做这件事。我(重新)学习的东西之一是C中的不同抽象技术与我以前在更高级别中使用的抽象技术语言。我遇到的问题,并询问,特别是与测试和功能有关。
例如,我有两个函数f
和g
,如果某些条件为真,f
会调用g
。
void f(object* obj) {
// ...
if(obj->state)
g(obj);
// ...
}
我需要验证g
实际上是被调用的,但我也不想实际执行它,因为它可以执行各种其他操作。这通常可以通过接口或抽象类或继承在更高级别的语言中解决。但是在C中我没有这些技术。
事实上,我能想到的唯一解决这个问题的方法是利用函数指针。我不应该直接调用g
,而是应该添加一个指向object
的指针,使其具有指向g
的指针,我可以用指向测试中不同函数的指针替换它。 / p>
typedef struct object {
int state;
void (*g)(object* obj);
} object;
void f(object* obj) {
// ...
if(obj->state)
obj->g(obj);
// ...
}
然后通常我只是在分配g
的实例时指向g
但是在我的测试中我将obj-> g指向另一个函数,一个仅仅验证传入值并注意到它实际上被称为。
这是我现在的想法,但我不确定它是否是解决此问题的正确C-ish方法。希望我的描述能说明我遇到的问题,但我真正想知道的是如何最好地处理它。
在C中解决此问题的推荐设计模式是什么?
答案 0 :(得分:1)
如果您要更改g
的不同来电中调用的f
函数,可能应将g
作为参数传递给f
:
typedef void (*gFunc)(object* obj);
void f(object *obj, gFunc g) {
...
if (obj->state) {
g(obj);
}
...
}
如果您不想弄乱f
的功能签名,可以定义f
版本来调用上述实现:
void gNormal(object* obj); //normal implementation of g
void gTest(object* obj); //test version of g
void fGeneral(object* obj, gFunc g); //general implementation of f as above
void fNormal(object* obj)
{
fGeneral(obj, &gNormal); //use the default version of g
}
无论您选择此方法还是使函数指针g
成为对象的成员,从语言的角度来看可能大致相同 - 您需要考虑对您的对象结构更有意义的内容。 / p>
然后,如果你做了很多这样的事情,也许你应该使用面向对象的语言!
答案 1 :(得分:0)
如果您在编译时知道是否要进入测试用例,则可以通过预处理器宏控制两种不同的g实现,如下所示:
#ifdef TESTING
int g() { // implement test version here }
#else
int g() { // implement real version here }
#endif
如果您只在编译时知道,可以以相同的方式使用全局变量,但两个实现都在相同的函数定义中:
int g() {
if (gTesting) {
// implement test version here
}
else {
// implement real version here
}
}