【问题标题】:Is there C macro for member methods?成员方法是否有 C 宏?
【发布时间】:2014-01-31 21:28:28
【问题描述】:

函数可以通过函数指针耦合到它们的引用结构。

struct string
{
    char *value;
    size_t (*size)(struct string *);
};

size_t size(struct string *this)
{
    size_t i;
for(i = 0; this->value[i] != '\0'; ++i);
return i;
}

struct string *construct()
{
    string this = (string)malloc(sizeof(struct string));
    this.size = &size;
    // ...
}

int main()
{
    struct string *s = construct();
    // ...
    s->size(s); // explicitly pass self reference
}

但我想摆脱手动传递this 指针。我知道当您调用对象的方法时,这是在 C++ 中隐式完成的。有没有办法在 C 中为此创建一个适用于所有方法和签名的宏?

例如,我可以想到这样的语法。

s=>size(); // implicitly pass self reference

请注意,这仅用于学习目的。我知道如果可能的话,最好只使用 C++,并且你想使用类耦合。但我对如何在 C 中完成它很感兴趣。

【问题讨论】:

  • 我认为CALL_METHOD(s, size) 太丑了,无法改进?
  • CALLMETHOD(objectref,methodname,otherargs) 当然可以,但是如果不对代码的外观进行一些类似的更改,我想不出任何方法。
  • @delnan 好吧,我不知道。所以这是不可能的。
  • 我的意思是,你可以使用 C++... ;-)
  • @immibis 这是一个“有可能吗?”问题,而不是“如何做到最好?”一。正如我已经说过的,仅用于学习目的。

标签: c class methods macros function-pointers


【解决方案1】:

是的,如果您能够使用variadic macros 功能,这是可能的:

// ...

#define CALL_METHOD(x, y, ...) x->y(x, ##__VA_ARGS__)

struct string
{
    char *value;
    size_t (*size)(struct string *);
    int (*compare)(struct string *, struct string *);
    int (*set_value)(struct string *, const char *);
};

// ...

int main()
{
    // ...

    CALL_METHOD(s1, set_value, "foo");
    CALL_METHOD(s2, set_value, "bar");

    printf("s1->size(s1) = %zu;\n", s1->size(s1));
    printf("CALL_METHOD(s1, size) = %zu;\n", CALL_METHOD(s1, size));
    printf("s1->compare(s1, s2) = %d;\n", s1->compare(s1, s2));
    printf("CALL_METHOD(s1, compare, s2) = %d;\n", CALL_METHOD(s1, compare, s2));

    // ...
}

【讨论】:

    【解决方案2】:

    你可以认为是 s->size() 语法。

    如果您考虑一个函数的多个范围,这是可能的。

    到海湾合作委员会

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct {
            const char *value;
            size_t (*size)();
            void (*destroy)();
    } string;
    
    #define STRING(A)                                               \
            string *A = (string *) malloc(sizeof(string));          \
            A->value = "";                                          \
            {                                                       \
                    size_t size() {                                 \
                            size_t i;                               \
                                                                    \
                            for(i = 0; A->value[i] != '\0'; ++i);   \
                            return i;                               \
                    }                                               \
                                                                    \
                    void destroy() {                                \
                            free(A);                                \
                    }                                               \
                                                                    \
                    A->size = &size;                                \
                    A->destroy = &destroy;                          \
            }
    
    int main() {
            printf("\n=== s1 ===\n");
            STRING(s1);
            printf("Size: %ld\n", s1->size());
            s1->value = "FOOO";
            printf("%s\n", s1->value);
            printf("Size: %ld\n", s1->size());
    
            printf("\n=== s2 ===\n");
            STRING(s2);
            printf("Size: %ld\n", s2->size());
            s2->value = "BAZ";
            printf("%s\n", s2->value);
            printf("Size: %ld\n", s2->size());
    
            printf("\n=== s1 ===\n");
            s1->value="A";
            printf("Size: %ld\n", s1->size());
            printf("%s\n", s1->value);
    
            printf("\n=== s2 ===\n");
            s2->value="ZZ";
            printf("Size: %ld\n", s2->size());
            printf("%s\n", s2->value);
    
            s1->destroy();
            s2->destroy();
    
            return 0;
    }
    

    标准C

    #include <stdio.h>
    #include <stdlib.h>
    
    #define STRING(A)                                               \
            string *A = (string *) malloc(sizeof(string));          \
            A->value = "";                                          \
            A->size = &size;                                        \
            A->destroy = &destroy;
    
    #define USE(A)                                                  \
            s = A;
    
    typedef struct {
            const char *value;
            size_t (*size)();
            void (*destroy)();
    } string;
    
    size_t size();
    void destroy();
    
    string *s;
    
    size_t size() {
            size_t i;
    
            for(i = 0; s->value[i] != '\0'; ++i);
            return i;
    }
    
    void destroy() {
            free(s);
    }
    
    int main() {
            printf("\n=== s1 ===\n");
            STRING(s1);
            USE(s1);
            printf("Size: %ld\n", s1->size());
            s1->value = "FOOO";
            printf("%s\n", s1->value);
            printf("Size: %ld\n", s1->size());
    
            printf("\n=== s2 ===\n");
            STRING(s2);
            USE(s2);
            printf("Size: %ld\n", s2->size());
            s2->value = "BAZ";
            printf("%s\n", s2->value);
            printf("Size: %ld\n", s2->size());
    
            USE(s1);
            printf("\n=== s1 ===\n");
            s1->value="A";
            printf("Size: %ld\n", s1->size());
            printf("%s\n", s1->value);
    
            USE(s2);
            printf("\n=== s2 ===\n");
            s2->value="ZZ";
            printf("Size: %ld\n", s2->size());
            printf("%s\n", s2->value);
    
            USE(s1);
            s1->destroy();
    
            USE(s2);
            s2->destroy();
    
            return 0;
    }
    

    【讨论】:

    • 您不能在标准 C 中使用嵌套函数(尽管您可以作为 GCC 扩展)。您的sizedestroy 代码将为s1 生成嵌套函数。
    • 我知道标准 c 不适用于嵌套函数。但答案解决了这个问题。还有一件事我不明白,s1 的嵌套函数有什么问题?
    猜你喜欢
    • 1970-01-01
    • 2010-09-11
    • 1970-01-01
    • 1970-01-01
    • 2013-07-07
    • 2011-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多