c – 为什么使用虚拟表而不是函数指针?

我是C的初学者,我无法理解为什么C使用虚拟表来实现多态而不是简单的函数指针.

我们来看一个例子:

struct Shape {
    virtual double area() = 0;
};

struct Square: public Shape {
    virtual double area();
    /* ... */
};

struct Circle: public Shape {
    virtual double area();
    /* ... */
};

double f(Shape &s) { return 42.0 + s.area(); }

C通常(总是?)如何实现多态:Shape和每个派生类都有一个指向虚拟表的隐藏指针作为第一个元素.当调用s.area()时,指向相应区域函数的指针取自s的虚拟表.

但是如果我不了解C和虚拟表并希望在C中实现这样的多态性,我会这样做:

struct Shape {
    double (*area)(struct Shape *this);
};

struct Square {  /* is a Shape */
    double (*area)(struct Square *this);
    /* ... */
};

struct Circle {  /* is a Shape */
    double (*area)(struct Circle *this);
    /* ... */
};

double f(struct Shape *s) { return 42.0 + s->area(s); }

double cirlce_area(struct Circle *this);
double square_area(struct Square *this);

/* ... */

struct Circle c = { &circle_area, ... };
printf("%f", f((struct Shape *)c));

当调用s-> area()时,使用来自s结构的第一个指针.

为什么C使用虚拟表而不是仅仅在结构的开头放置指向虚函数的指针(具有相同的顺序)?我目前无法找到任何理由为什么最后一种方法可能无效.

解决方法:

从概念上讲,这是完全相同的事情.

虚方法表不是函数指针列表.它没有集成在对象本身中,因为它对于对象的类是静态的,因此它可以在同一个类的实例之间共享(在对象整个生命周期中保存初始化期间的计算能力和内存).

具体来说,在C中,每个构造函数都将虚方法表指针设置为它所属的类的指针.因此,在最外层构造函数运行之后,虚方法将解析为该对象所在的类.

上一篇:c – 如果您的基类具有虚拟析构函数,则您自己的析构函数将自动为虚拟


下一篇:c – 缓存优化和多态性