用类加入C

And*_*rea 9 c oop

免责声明:我是C的完全新手,但我一直在玩它试图模仿一些类的功能.好吧,我知道如果我想这样,我应该学习C++,但请考虑以下一点实验.

Schreiner,在使用ANSI-C的面向对象编程一书中提出了一种使用指针在C中获取面向对象特征的方法.我必须承认我只是浏览了这本书,但我不太喜欢他的方法.基本上,他使用函数指针来安排

func(foo);
Run Code Online (Sandbox Code Playgroud)

实际上导致了呼唤

foo.methods->func();
Run Code Online (Sandbox Code Playgroud)

哪个foo.methods是包含函数指针的结构.在这种方法中我不喜欢的是,foo无论如何必须具有全局功能; 也就是说,方法没有被它们所居住的类命名.我的感觉是这很快就会导致混乱:想想两个对象,foo并且bar都有一个方法func但参数数量不同.

所以我试图找到更符合我口味的东西.第一次尝试是以下(我为了简洁省略了声明)

#include <stdio.h>

//Instances of this struct will be my objects
struct foo {
    //Properties
    int bar;

    //Methods
    void (* print)(struct foo self);
    void (* printSum)(struct foo self, int delta);
};

//Here is the actual implementation of the methods
static void printFoo(struct foo self) {
    printf("This is bar: %d\n", self.bar);
}

static void printSumFoo(struct foo self, int delta) {
    printf("This is bar plus delta: %d\n", self.bar + delta);
}

//This is a sort of constructor
struct foo Foo(int bar) {
    struct foo foo = {
        .bar = bar,
        .print = &printFoo,
        .printSum = &printSumFoo
    };
    return foo;
}

//Finally, this is how one calls the methods
void
main(void) {
    struct foo foo = Foo(14);
    foo.print(foo); // This is bar: 14
    foo.printSum(foo, 2); // This is bar plus delta: 16
}
Run Code Online (Sandbox Code Playgroud)

这是不方便但有点工作.但是,我不喜欢的是你必须明确地将对象本身添加为第一个参数.通过一些预处理器工作,我可以做得更好一点:

#include <stdio.h>
#define __(stuff)     stuff.method(* stuff.object)

//Instances of this struct will be my objects
struct foo {
    //Properties
    int bar;

    //Methods
    //Note: these are now struct themselves
    //and they contain a pointer the object...
    struct {
        void (* method)(struct foo self);
        struct foo * object;
    } print;
};

//Here is the actual implementation of the methods
static void printFoo(struct foo self) {
    printf("This is bar: %d\n", self.bar);
}

//This is a sort of constructor
struct foo Foo(int bar) {
    struct foo foo = {
        .bar = bar,
        //...hence initialization is a little bit different
        .print = {
            .method = &printFoo,
            .object = &foo
        }
    };
    return foo;
}

//Finally, this is how one calls the methods
void
main(void) {
    struct foo foo = Foo(14);
    //This is long and unconvenient...
    foo.print.method(* foo.print.object); // This is bar: 14
    //...but it can be shortened by the preprocessor
    __(foo.print); // This is bar: 14
}
Run Code Online (Sandbox Code Playgroud)

这是我能得到的.这里的问题是它不适用于带参数的方法,因为预处理器宏不能采用可变数量的参数.当然,你可以定义宏_0,_1等根据参数的个数(直到一个累了),但是这不是一个好办法.

有没有办法改进这一点,让C使用更面向对象的语法?

我应该补充一点,实际上Schreiner比我在他的书中说的要多得多,但我认为基本结构不会改变.

APr*_*mer 2

各种框架已经存在。例如参见http://ldeniau.web.cern.ch/ldeniau/html/oopc.html