Так что, ради «весело», я решил эмулировать функции-члены C++
в C
с использованием функций указателя. Вот простой код:Использование функций указателя для эмулирования функций-членов в C-структурах
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;
}
Выход:
>./a.out
Value = 10
При этом я решил, что мне нужно было эмулировать роль неявного указателя this
, явно передавая его моим функциям-членам. Это прекрасно работает, я думаю, кроме того, что все это выглядит странно!
Если бы я хотел передать объект, почему бы реализовать функции как функции-члены? Единственный ответ, который я нашел, это, возможно, в тех случаях, когда вы хотели бы иметь унифицированный интерфейс, но различные реализации? (что-то похоже на C++
виртуальные функции?)
Что (если есть) некоторые другие причины для эмулирования функций-членов? Кроме того, есть ли способ обойти простую явную указатель this_
?
EDIT: При передаче объекта возникла проблема с исходным кодом. Я использовал &a
по ошибке для функций read/set
. Вам понадобится только для deleteObj
, если вы хотите установить указатель на NULL
внутри.
Вы передаете _address_ указателя на функции, то есть 'Obj **'. Пропустите '&' в вызовах функций. –
@JoachimPileborg: Вы правы.Пожалуйста, см. Мое редактирование. – GradGuy
Мне когда-то приходилось поддерживать унаследованный проект с использованием аналогичного подхода со сложной иерархией наследования и добавленным извращением использования непрозрачных значений intpedef't, а не указателей на структуры. Излишне говорить, что это был кошмар для отладки/поддержки! – SirDarius