对于当前项目,我不能使用C ++(不幸的是),只能使用纯C,而且我有以下问题:
我有3个独特的结构,需要调用相同的函数名称,我感觉它更优雅的方式在下面,而不是为不同的类型创建3个不同的功能,就像我觉得它更容易维护。如何获取调用该函数的指针?基本上我正在尝试重现的内容基本上与C ++中的“this”或者自我(在Obj-C中)类似,无论如何我可以在普通的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;
}
答案 0 :(得分:0)
执行此类操作的传统方法(例如在UNIX内核中)是使用#define
语法糖:
#define GET_TYPE(X) ((X)->GetType((X)))
当然,如果有更多的论据,它也会传递这些论点。函数指针通常收集在一个静态“ops”结构中,该结构在创建时分配(而不是每个单独的函数指针)。每个ops向量都有一个相应的#defines
集合。
答案 1 :(得分: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(),只需更改base中的指针即可。您可以保存指向my_base的指针并动态解析类型。
答案 2 :(得分:0)
将此作为正常参数传递(首先是常规参数):
void GetType(void *this);
...
GetType(a); // instead of C++-style a->GetType
最好有一些“基类”(包括“int type”字段),在这种情况下,指针将是“struct Base * this”,而不是“void * this”。
我个人总是这样走。您可以为某些“类”的函数添加前缀(例如,Cl1_GetType)。这是C语言中的OO编程方式。也可以使用通过函数指针的“真实虚函数”,但这不是常见的情况。
答案 3 :(得分: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;
}
希望这能回答你的问题。