The function (*differ)() is a member of the the struct Class. So
it operates on Class's instance, right? For example:
Class *myclass = (Class*)malloc(sizeof(Class));
myclass->differ();
3 minor points:
1. Casting the result of a call to 'malloc' is discussed in the C FAQ's
question 7.7b:
http://c-faq.com/malloc/mallocnocast.html
2. If possible, please try to use the idiom:
complete_obj_type * some_obj = malloc(sizeof *some_obj);
Because 'sizeof' is not a function, it is an operator, and because it's
more specific to say that you're allocating storage for 'some_obj',
rather than to say that you're allocating storage for the type of
'some_obj'.
3. It's a good idea to check the result of your 'malloc' call before
using the object. You can do this with an 'assert' for development, or
you can actually handle the case where there's insufficient memory and
fail gracefully.
So adjusting your example:
Class *myclass = malloc(sizeof *myclass);
if (!myclass) {
/* Code to fail gracefully */
}
It's also worth noting that you haven't yet set the 'myclass->differ'
function pointer to anything, so that pointer value is indeterminate
until you do so. And you need to pass arguments that satisfy the
pointed-to function's parameter expectations.
But I don't know if you'd want to use 'malloc' for such a thing. You
might use something like:
Class *myclass = NewClass(sizeof *myclass);
if (!myclass) {
/* Code to fail gracefully */
}
where 'NewClass' might be something like:
#include <stddef.h>
#include <assert.h>
void DefaultClass(Class * class) {
static const Class default_class = {
sizeof default_class,
default_ctor,
default_dtor,
default_clone,
default_differ,
};
assert(class);
*class = default_class;
}
Class * NewClass(size_t class_sz) {
Class * result;
if (class_sz < sizeof *result) {
assert(!"Insufficient class size");
return NULL;
}
result = malloc(class_sz);
if (result) {
DefaultClass(result);
result->size = class_sz;
}
return result;
}
(Where each of the default_* functions are actually defined somewhere.)
That way, when you produce a new 'Class', you immediately throw some
useful defaults into it. This is a suggestion for a bit of "protection"
against programming errors and does incur overhead, so it's certainly up
to you.
- Shao Miller