用C模拟的虚函数

时间:2019-05-21 20:43:40

标签: c function virtual

我有一个用C语言编写的代码示例,它模拟了虚函数Shape_area()。

我不懂一行代码:return (*me->vptr->area)(me);

为什么在“我”之前使用“ *”?

您能告诉我那部分吗? 谢谢

/*shape.h*/

struct ShapeVtbl; /* forward declaration */
typedef struct {
    struct ShapeVtbl const *vptr; /* <== Shape's Virtual Pointer */
    int16_t x; /* x-coordinate of Shape's position */
    int16_t y; /* y-coordinate of Shape's position */
} Shape;

/* Shape's virtual table */
struct ShapeVtbl {
    uint32_t (*area)(Shape const * const me);
};

/* Shape's operations (Shape's interface)... */
void Shape_ctor(Shape * const me, int16_t x, int16_t y);
void Shape_moveBy(Shape * const me, int16_t dx, int16_t dy);

uint32_t Shape_area(Shape const * const me) {
    return (*me->vptr->area)(me);
}

2 个答案:

答案 0 :(得分:6)

如果它是一个函数指针,则不是必需的。不管有没有,都一样。

这个想法是,它是一个“指向函数的指针”,因此您希望取消对指针的引用,以便能够将其用作函数。但是函数名称实际上实际上也只是指针,并且您也不需要取消引用它们,因此它们是等效的。

expected = pd.DataFrame({ 'CREATED_DT_DTTM_EPOCH': [ 1483302261, 1483305054, 1483357692, 1483385453, 1483391215 ], 'Audit_Epoch': [0,1483383670,0,0,0], 'Difference': [ 1483302261, 78616, 1483357692, 1483385453, 1483391215 ] }) 等效于(*me->vptr->area)(me),而(me->vptr->area)(me)等效于printf("foo")(尽管您永远不会这样写)。

您可以保留它或将其删除,这并不重要。就个人而言,如果它专门是指向函数的指针而不是命名函数本身,那么我将保留它,以保持“取消使用它”的想法。

答案 1 :(得分:2)

函数Shape_area()定义为:

uint32_t Shape_area(Shape const * const me) {
    return (*me->vptr->area)(me);
}

这意味着函数Shape_area()接受一个指向Shape类型的结构的指针。

因此,为了获得虚拟函数的实际函数指针,各种结构的定义如下。

第一个结构是实际的数据结构,其中包含数据以及虚函数指针。

typedef struct {
    struct ShapeVtbl const *vptr; /* <== Shape's Virtual Pointer */
    int16_t x; /* x-coordinate of Shape's position */
    int16_t y; /* y-coordinate of Shape's position */
} Shape; 

有两个数据项xy,以及指向虚拟指针的指针,该指针将包含指向要使用的实际函数的指针。

指向虚函数的指针包含一个结构,并定义为:

struct ShapeVtbl {
    uint32_t (*area)(Shape const * const me);
};

因此,如果我们使用这些数据结构之一,它将类似于以下源代码片段。

uint32_t doVirt (Shape const * const me)
{
    // do things with the x and y data from variable me.
    // reference me->x and me->y to access those values.

    return 0;
}

struct ShapeVtbl myVirt = { doVirt };  // create a struct containing pointer to our function

Shape myShape;    // define our data structure

myShape.x = 32;          // set the x coordinate
myShape.y = 45;          // set the y coordinate
myShape.vptr = &myVirt;  // set the pointer to the virtual function pointer.

Shape_area (&myShape);   // call Shape_area with our struct.

函数Shape_area()将指向myShape结构的指针,然后访问通过提供的函数指针指定的虚函数。

如果我们查看operator precedence table,我们会发现*me->vptr->area*(me->vptr->area)相同,或者换句话说,星号用于使用标准指针取消引用语法来取消引用功能指针。

但是对于函数指针,虽然仍然可以使用此语法,但这不是必需的。因此,由于运算符优先级规则,(*me->vptr->area)()(me->vptr->area) ()相同,与me->vptr->area()相同。