我无法理解 Google 的 V8 JavaScript 引擎中继承的实现。它显然(?)实现了继承层次结构,但似乎完全取消了虚函数。
这是 objects.h
header file 中详述的继承层次结构:
// Inheritance hierarchy:
// - Object
// - Smi (immediate small integer)
// - HeapObject (superclass for everything allocated in the heap)
// - JSReceiver (suitable for property access)
// - JSObject
// - JSArray
// ... and many more entries
大多数对象类型都派生自Object
,声明如下:
// Object is the abstract superclass for all classes in the
// object hierarchy.
// Object does not use any virtual functions to avoid the
// allocation of the C++ vtable.
// Since both Smi and HeapObject are subclasses of Object no
// data members can be present in Object.
class Object {
// ... bunch of method declarations and definitions
};
接下来声明相对简单的Smi
类:
class Smi: public Object {
public:
// methods declarations and static member definitions
};
等等。
在我的生活中,我无法理解,比方说,Smi
的实例如何可以用作Object
; 没有虚函数并且我在the implementation file, objects.cc
中找不到覆盖。但是,在 17,290 行中,试图了解正在发生的事情被证明是一项艰巨的任务。
作为另一个困难,我在同一个头文件中找到了一个 ObjectVisitor
类(这个更经典;它由虚拟方法组成)。但是我在 Object
基类中找不到等效的 Accept(Visitor*)
(或类似的)方法。
我具体要问的是一个最小的例子来说明这种继承模式是如何工作的。
最佳答案
objects.h 中的类实际上并没有定义真正的 C++ 类。他们没有任何领域。这些类仅仅是 V8 JavaScript 堆上管理的对象的外观。因此它们也不能有任何虚函数,因为那需要将 vtable 指针放入 JS 堆中。相反,所有分派(dispatch)都是通过显式类型检查和向下转换手动完成的。
方法中的 this
指针也不是真实的。对于 smis,this
只是一个整数。对于其他所有内容,它都是一个指向 V8 堆的指针,为了标记而减一。任何实际的访问器方法都会屏蔽此指针并添加偏移量以访问堆中的适本地址。每个字段的偏移量也在类中手动定义。
关于c++ - 了解 Google 的 V8 C++ 代码库中的继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31506379/