Object-orientation in C

前端 未结 22 1558
孤城傲影
孤城傲影 2020-11-22 15:26

What would be a set of nifty preprocessor hacks (ANSI C89/ISO C90 compatible) which enable some kind of ugly (but usable) object-orientation in C?

I am familiar with

22条回答
  •  情话喂你
    2020-11-22 16:16

    If you really thinks catefully, even standard C library use OOP - consider FILE * as an example: fopen() initializes an FILE * object, and you use it use member methods fscanf(), fprintf(), fread(), fwrite() and others, and eventually finalize it with fclose().

    You can also go with the pseudo-Objective-C way which is not difficult as well:

    typedef void *Class;
    
    typedef struct __class_Foo
    {
        Class isa;
        int ivar;
    } Foo;
    
    typedef struct __meta_Foo
    {
        Foo *(*alloc)(void);
        Foo *(*init)(Foo *self);
        int (*ivar)(Foo *self);
        void (*setIvar)(Foo *self);
    } meta_Foo;
    
    meta_Foo *class_Foo;
    
    void __meta_Foo_init(void) __attribute__((constructor));
    void __meta_Foo_init(void)
    {
        class_Foo = malloc(sizeof(meta_Foo));
        if (class_Foo)
        {
            class_Foo = {__imp_Foo_alloc, __imp_Foo_init, __imp_Foo_ivar, __imp_Foo_setIvar};
        }
    }
    
    Foo *__imp_Foo_alloc(void)
    {
        Foo *foo = malloc(sizeof(Foo));
        if (foo)
        {
            memset(foo, 0, sizeof(Foo));
            foo->isa = class_Foo;
        }
        return foo;
    }
    
    Foo *__imp_Foo_init(Foo *self)
    {
        if (self)
        {
            self->ivar = 42;
        }
        return self;
    }
    // ...
    

    To use:

    int main(void)
    {
        Foo *foo = (class_Foo->init)((class_Foo->alloc)());
        printf("%d\n", (foo->isa->ivar)(foo)); // 42
        foo->isa->setIvar(foo, 60);
        printf("%d\n", (foo->isa->ivar)(foo)); // 60
        free(foo);
    }
    

    This is what may be resulted from some Objective-C code like this, if a pretty-old Objective-C-to-C translator is used:

    @interface Foo : NSObject
    {
        int ivar;
    }
    - (int)ivar;
    - (void)setIvar:(int)ivar;
    @end
    
    @implementation Foo
    - (id)init
    {
        if (self = [super init])
        {
            ivar = 42;
        }
        return self;
    }
    @end
    
    int main(void)
    {
        Foo *foo = [[Foo alloc] init];
        printf("%d\n", [foo ivar]);
        [foo setIvar:60];
        printf("%d\n", [foo ivar]);
        [foo release];
    }
    

提交回复
热议问题