使用成员函数访问struct内的成员?

时间:2016-07-12 00:36:29

标签: c

假设我有以下结构

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变量,但我不知道如何执行此操作,或者如果可能的话

有没有办法让我的代码做我想要的?谢谢!

我在评论中解释了为什么这个问题不是链接的问题的重复。

3 个答案:

答案 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!" */