为什么使用虚拟表代替函数指针
Why use a virtual table instead of function pointers?
我是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()
时,指向相应的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 中,每个构造函数都将虚拟方法表指针设置为其所属类的指针。因此,在最外面的构造函数运行之后,虚拟方法解析为对象为。
考虑包含许多虚拟方法的类将发生的事情:您必须为每个实例分别支付存储x函数pointer 的成本。这可能很快变得非常浪费。
使用VPTR还可以帮助实现其他语言功能:易于使用VPTR的值来确定对象的运行时类型(想想typeid
)。
相关文章:
- QMetaObject invokeMethod的基于函数指针的语法
- C++-试图将函数指针推回到另一个CPP文件中的矢量时出错
- c++r值引用应用于函数指针
- 模板函数指针和lambda
- 是否可以将llvm::FunctionType转换为C/C++原始函数指针
- 带有类的函数指针
- () 函子后面的括号,而不是函数指针?
- 全局作用域中函数指针的赋值
- 使用"Task"函数指针队列定义作业管理器
- 将成员函数指针作为参数传递给模板方法
- 如何创建对象函数指针C++映射?
- 匹配函数指针作为模板参数?
- 通过函数指针定义类范围之外的方法
- 存储在类中的函数指针
- C++从函数指针数组调用函数
- 将返回值存储在函数指针数组的指针中是如何工作的?
- 整数键映射到头文件中的成员函数指针
- 从类成员函数到类 C 函数指针的转换
- 如何将内联匿名函数分配给C++函数指针
- 将字符缓冲区强制转换为函数指针