Я недавно взял на себя задачу реализовать классы (полиморфизм и все) в C. То есть - реализовать структуру данных, которая имеет свои собственные методы, может наследовать другие такие структуры и (из-за своего наследования) может быть Тип, нацеленный как один из его предков.
Как вы уже догадались, я использую structs
как classes
. Я использую указатели функций для эмуляции методов, хотя они все еще требуют ручной передачи им this
. Чтобы эмулировать наследование, я решил #pragma pack(8)
всех своих классов, а затем скопировать и вставить поля унаследованного класса в дочерний класс:
#define _Entity_Content int id;\
char *name;
#define inherits(x) _ ## x ## _Content
Пусть Y
наследует X
. При передаче this
методу X
из Y
я бы передал указатель на Y
. С #pragma pack(8)
это сработает один раз, поскольку любое последующее наследование нарушит простую запись &myclass
. Решением было бы рассчитать смещения для начала каждого класса (возможно, с pack(1)
).
Еще одна, и более важная проблема заключается в том, что, хотя все это было бы возможно, это было бы неудобно для пользователя, а также просто уродливо (иметь #define
содержимое каждого struct
и т. Д.)
Это то, что у меня сейчас:
#define _Person_ char *name;\
int age;\
char *(*getName)(struct Person *);\
void (*incrementAge)(struct Person *);
#define superclass(identifier) _ ## identifier ## _
#pragma pack(8)
struct Person {
superclass(Person);
};
#pragma pack(8)
struct Man {
superclass(Person);
struct Person *family;
};
// let man be struct Man
man.incrementAge(&man);
И в идеальном мире:
#pragma pack(8)
class(Person, char *name;
int age;
etc.
);
#pragma pack(8)
superclass(Person)
class(Man, struct Person *family;);
Какие уловки я могу использовать, чтобы улучшить пользовательский опыт, так как это главная цель моего проекта?