So just for the sake if having ”fun” I decided to emulate C++ member functions in C using pointer functions. Here is a simple code:
obj.h:
#ifndef OBJ_H
#define OBJ_H
#include <stdlib.h>
#include <stdio.h>
struct Obj{
struct pObjVar* pVar;
void (*read)(struct Obj*);
void (*set) (struct Obj*, int);
};
struct Obj* newObj();
void deleteObj(struct Obj** obj);
#endif
obj.c:
#include "obj.h"
void readValue(struct Obj* this_);
void setValue (struct Obj* this_, int mValue_);
struct pObjVar{
int mValue;
};
struct Obj* newObj(){
struct Obj* tmp = (struct Obj*) malloc(sizeof(struct Obj));
tmp->pVar = (struct pObjVar*) malloc(sizeof(struct pObjVar));
tmp->pVar->mValue = 0;
tmp->read = readValue;
tmp->set = setValue;
return tmp;
}
void deleteObj(struct Obj **obj){
free((*obj)->pVar); (*obj)->pVar = NULL;
free((*obj)); *obj = NULL;
}
void readValue(struct Obj *this_){
printf("Value = %d\n",this_->pVar->mValue);
}
void setValue(struct Obj *this_, int mValue_){
this_->pVar->mValue = mValue_;
}
main.c:
#include "obj.h"
int main(void)
{
struct Obj* a = newObj();
a->set(a, 10);
a->read(a);
deleteObj(&a);
return 0;
}
Output:
>./a.out
Value = 10
In doing this, however, I figured I had to emulate the role of implicit this pointer by explicitly passing it to my member functions. This works fine, I guess, except that it makes the whole thing look weird!
If I wanted to pass the object, why would implement the functions as member functions? The only answer I found to it was maybe in cases where you would want to have a unified interface but various implementations? (something similar to C++ virtual functions?)
What are (if any) some other reasons to emulate member functions? Also, is there any way to get around passing the explicit this_ pointer at all?
EDIT: There was problem in the original code when passing the object. I was using &a by mistake for the read/set functions. You would only need it for the deleteObj if you want to set the pointer to NULL internally.
Just another way of writing:
This can be used for implementing interfaces, inheritance and many C++ features, which were implemented like this in C with Classes times. In Linux kernel, file operations are implemented like this. File structure stores pointers to functions, so that each file system can store it’s own system call handlers that operate on/with the data in the structure.