假设我有以下结构
struct Being{
int canFly;
int (*printFlying)();
}
我想做以下事情:
int main(){
struct Being * flyingThing = new_flyingThing();
struct Being * thingThatCantFly = new_Thing();
flyingThing->printFlying(); /* "I'm flying!" */
thingThatCantFly->printFlying(); /* "I can't fly!" */
}
看起来我需要printFlying
函数才能访问结构中的canFly
变量,但我不知道如何执行此操作,或者如果可能的话
有没有办法让我的代码做我想要的?谢谢!
我在评论中解释了为什么这个问题不是链接的问题的重复。
答案 0 :(得分:2)
C不是面向对象的语言,因此函数成员无法自动知道使用哪个结构来调用它。
由于每个结构都有自己的函数指针,您可以通过让它们引用不同的函数来获得您想要的结果,这些函数会打印相应的消息,而不是从can_fly
成员获取它。
int print_flying_thing() {
printf("I'm flying!\n");
}
struct Being *new_flyingThing() {
struct Being *thing = malloc(sizeof(struct Being));
thing->can_fly = 1;
thing->printFlying = print_flying_thing;
return thing;
}
int print_nonflying_thing() {
printf("I can't fly!\n");
}
struct Being *new_Thing() {
struct Being *thing = malloc(sizeof(struct Being));
thing->can_fly = 0;
thing->printFlying = print_nonflying_thing;
return thing;
}
答案 1 :(得分:1)
printFlying
指针指向的函数无法访问包含struct Being
结构的成员,除非它给出了引用该结构的参数。 (或者它可以通过其他方式访问结构,可能通过全局变量,但参数是最干净的方式。)
例如,考虑两个类型为struct Being
的对象,它们的printFlying
指针都指向同一个函数。这个功能无法分辨它与之相关的两个对象中的哪一个 - 因为它与它们中的任何一个都没有联系。
C ++成员函数可以这样做,因为它们会给出一个隐式指针参数,通过this
关键字在函数内部引用。 C没有这样的功能。
你可能会创建一个类似的宏,但我怀疑这是值得的。
您是否考虑过使用C ++?
答案 2 :(得分:1)
对于这个特殊的例子,你似乎真正想要的是能够有一个指向两个不同功能的函数指针,一个用于实现飞行,另一个用于实现不飞行。
所以我会考虑采用的方法如下。我没有尝试过编译这段代码,但这种感觉是正确的。
同样在您的评论中,您提到过阻止更改功能指针。您可以执行以下操作,其中const
被添加到函数指针的结构定义中,然后使用带有强制转换的结构的克隆。
头文件flying.h内容。
typedef struct _TAG_Being {
int (* const printFlying)();
} Being;
Being * new_flyingThing ();
Being * new_Thing();
实施或flying.c文件。
#include "flying.h"
static int printFlyingThing()
{
printf (" I am a flying thing\n");
return 0;
}
static int printThing()
{
printf (" I am a thing\n");
return 1;
}
// use the same layout and members as Being above.
typedef struct {
int (* printFlying)();
} BeingX;
Being * new_flyingThing ()
{
BeingX *p = malloc(sizeof(BeingX));
p->printFlying = printFlyingThing; // use the flying thing function
{
Being *q = (Being *)p;
return q;
}
}
Being * new_Thing()
{
BeingX *p = malloc(sizeof(BeingX));
p->printFlying = printThing; // use the not flying thing function.
{
Being *q = (Being *)p;
return q;
}
}
主要或使用.c文件
#include "flying.h"
int main(){
Being * flyingThing = new_flyingThing();
Being * thingThatCantFly = new_Thing();
flyingThing->printFlying(); /* "I'm flying!" */
thingThatCantFly->printFlying(); /* "I can't fly!" */
}
如果您需要访问Being
函数中的实际printFlying()
对象或变量,则需要将其作为参数传递。
例如:
typedef struct _TAG_Being {
int xx;
int (*printFlying)(struct _TAG_Being *p);
} Being;
然后你需要这样的东西:
Being * flyingThing = new_flyingThing();
flyingThing->printFlying(flyingThing); /* "I'm flying!" */