2011-04-28 76 views
3

的指针对于目前的项目,我不能使用C++(不幸的),只有纯粹的C,和Im具有以下问题:获取结构调用函数

我有3个独特的结构需要调用同一个函数名,我觉得它的方式更优雅,而不是为不同类型创建3种不同的功能,就像我觉得它更容易维护。我怎样才能得到调用函数的指针?基本上我想重现的基本上与C++或self(在Obj-C)中的“this”类似,无论如何我可以在纯C中做到这一点?

[test.h]

enum 
{ 
    TYPE_A = 0, 
    TYPE_B = 1, 
    TYPE_C = 2 
}; 

typedef struct 
{ 
    char type;  
    void (*GetType)(void); 
    // Some other data different than the other struct 
}A; 


typedef struct 
{ 
    char type; 
    void (*GetType)(void); 
    /* Some other data different than the other struct */ 
}B; 


typedef struct 
{ 
    char type; 
    void (*GetType)(void); 
    // Some other data different than the other struct 
} C; 

A *create_a(void); 

B *create_b(void); 

C *create_c(void); 

void GetType(void); 

[test.c的]

A *create_a(void) 
{ 
    A *a = (A *) calloc(1, sizeof(A)); 
    a->type = TYPE_A; 
    a->GetType = GetType; 
    return a; 
} 

B *create_b(void) 
{ 
    B *b = (B *) calloc(1, sizeof(B)); 
    b->type = TYPE_B; 
    b->GetType = GetType; 
    return b; 
} 


C *create_c(void) 
{ 
    C *c = (C *) calloc(1, sizeof(C)); 
    c->type = TYPE_C; 
    c->GetType = GetType; 
    return c; 
} 


void GetType(void) 
{ 
    printf("How to get the pointer that call this function to retrieve the type?"); 
} 

[main.c中]

int main (int argc, const char * argv[]) 
{ 
    A *a = create_a(); 
    B *b = create_b(); 
    C *c = create_c(); 

    a->GetType(); 
    b->GetType(); 
    c->GetType(); 

    return 0; 
} 
+2

如果你足够深入这个兔子洞,你将最终重塑C++。 – 2011-04-28 08:13:33

+0

但是只要我们重新实现C++,你应该使用vtables而不是每个对象的函数指针。 – 2011-04-28 08:15:54

回答

0

传统的方式做这种事情(例如在UNIX内核中)通过使用#define来获得语法糖:

#define GET_TYPE(X) ((X)->GetType((X))) 

当然,如果有更多的参数,它也会传递这些参数。函数指针通常收集在创建时分配的一个静态“操作”结构中(而不是每个单独的函数指针)。每个操作矢量都有相应的集合#defines

0

“this”应作为GetType()的参数给出。这就是对象方法实际上在底层实现的方式。而且,由于GetType应该能够与所有类型的结构进行交互 - 结构应该有一个类似的“基类”。例如:

#include "stdio.h" 

typedef enum 
{ 
TYPE_A = 0, 
TYPE_B = 1, 
TYPE_C = 2 
} my_class_type; 

typedef struct 
{ 
char type;  
my_class_type (*GetType)(void*); 
}my_base; 

my_class_type my_base_GetType(void* my_base_ptr) 
{ 
    return ((my_base*)my_base_ptr)->type; 
} 

typedef struct 
{ 
    my_base base; 
    // Some other data different than the other struct 
}A; 


typedef struct 
{ 
    my_base base; 
/* Some other data different than the other struct */ 
}B; 


typedef struct 
{ 
    my_base base; 
// Some other data different than the other struct 
}C; 

A *create_a(void) 
{ 
A *a = (A *) calloc(1, sizeof(A)); 
a->base.type = TYPE_A; 
a->base.GetType = my_base_GetType; 
return a; 
} 

B *create_b(void) 
{ 
B *b = (B *) calloc(1, sizeof(B)); 
b->base.type = TYPE_B; 
b->base.GetType = my_base_GetType; 
return b; 
} 


C *create_c(void) 
{ 
C *c = (C *) calloc(1, sizeof(C)); 
c->base.type = TYPE_C; 
c->base.GetType = my_base_GetType; 
return c; 
} 




int main(int argc, char* argv[]) 
{ 
    A *a = create_a(); 
    B *b = create_b(); 
    C *c = create_c(); 

    printf("%d\n",a->base.GetType(a)); 
    printf("%d\n",b->base.GetType(b)); 
    printf("%d\n",c->base.GetType(c)); 
    return 0; 
} 

这个例子实现了继承和多态。所有结构共享相同的基本核心,如果你想重写GetType(),你只需要改变基地的指针。您可以持有指向my_base的指针并动态解析类型。

+0

可否请您详细说明一个例子。 – McBob 2011-04-28 08:00:49

0

通这个作为一个正常的参数(第一,是常规的):

void GetType(void *this); 
... 
GetType(a); // instead of C++-style a->GetType 

它最好能够有一些“基类”(包括“的int类型”字段中),在这种情况下指针将是“struct base * this”,而不是“void * this”)。

就我个人而言,我总是这样。您可以为某些“类”的函数添加前缀(例如,Cl1_GetType)。这是用C编写OO编程的方式。也可以使用通过函数指针的“真正的虚拟函数”,但并不是这种常见的情况。

0

从我了解你的问题是:“你只是想获得在的GetType函数的结构类型字段的值”。这是正确的吗?如果是的话,你可以这样来做:

enum 
{ 
    TYPE_A = 0, 
    TYPE_B = 1, 
    TYPE_C = 2 
}; 

typedef struct 
{ 
    char type;  
    // Some other data different than the other struct 
}A; 


typedef struct 
{ 
    char type;  
    /* Some other data different than the other struct */ 
}B; 


typedef struct 
{ 
    char type; 
    // Some other data different than the other struct 
} C; 


A *create_a(void); 

B *create_b(void); 

C *create_c(void); 

void GetType(void *); 

[test.c的]

A *create_a(void) 
    { 
     A *a = (A *) calloc(1, sizeof(A)); 
     a->type = TYPE_A; 
     return a; 
    } 

    B *create_b(void) 
    { 
     B *b = (B *) calloc(1, sizeof(B)); 
     b->type = TYPE_B; 
     return b; 
    } 

    C *create_c(void) 
    { 
     C *c = (C *) calloc(1, sizeof(C)); 
     c->type = TYPE_C; 
     return c; 
    } 
#define GetType(x) (x->type) 

[main.c中]

int main (int argc, const char * argv[]) 
{ 
    A *a = create_a(); 
    B *b = create_b(); 
    C *c = create_c(); 

    GetType(a); 
    GetType(b); 
    GetType(c); 

    return 0; 
} 

希望这回答了你的问题。