Reputation: 13675
I am not a C expert. I haven't done any C since my CS1 & 2 days in college. I have done a little C++ here and there but it's been a while. So what I'm asking about is the correct pattern to solve a problem I am perceiving.
I have decided to take on a fairly ambitious challenge and I am doing it in C. One of the things I am (re)learning is the different abstraction techniques in C vs. the ones I am used to having in higher level languages. The problem I am encountering, and asking about, specifically has to do with testing and functions.
For example, I have two functions f
and g
and f
will call g
if certain conditions are true.
void f(object* obj) {
// ...
if(obj->state)
g(obj);
// ...
}
I need to verify that g
is actually being called but I also don't want to actually execute it, since it can do all sorts of other things. This would normally be solved in a higher level language by means of interfaces or abstract classes or inheritance. But in C I don't have these techniques.
In fact the only solution to this problem that I can think of is to utilize function pointers. Instead of calling g
directly I think I should add a pointer to object
such that it has a pointer to g
, which I can replace with a pointer to a different function in tests.
typedef struct object {
int state;
void (*g)(object* obj);
} object;
void f(object* obj) {
// ...
if(obj->state)
obj->g(obj);
// ...
}
Then normally I just point to g
when allocating an instance of g
but in my test I point obj->g to a different function, one that merely verifies the incoming values and notes that it was actually called.
This is the idea I am having right now but I'm not sure if it's quite the correct C-ish way to solve this problem. Hopefully my description illustrates the problem I am encountering but what I am really wondering is how best to handle it.
What are the recommended design patterns for solving this problem in C?
Upvotes: 2
Views: 120
Reputation: 3251
If you want to change the function g
called in different calls of f
, maybe you should pass in g
as a parameter to f
:
typedef void (*gFunc)(object* obj);
void f(object *obj, gFunc g) {
...
if (obj->state) {
g(obj);
}
...
}
If you didn't want to mess up the function signature of f
, you can define a version of f
to call the above implementation:
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
}
Whether you choose this method or to make the function pointer g
a member of the object is probably about the same from the language's point of view - you need to consider what makes more sense for your object structure.
Then again, if you are doing lots of stuff like this, maybe you should be using an object-oriented language!
Upvotes: 1
Reputation: 1419
If you know at compile time whether you want to be in the testing case, you can have two different implementations of g that are controlled via preprocessor macros, so something like:
#ifdef TESTING
int g() { // implement test version here }
#else
int g() { // implement real version here }
#endif
If you only know at compile time, you could give use a global variable in the same way, but with both implementations in the same function definition:
int g() {
if (gTesting) {
// implement test version here
}
else {
// implement real version here
}
}
Upvotes: 0