6

The most popular way (or so I heard) seems to be a virtual table, but what other alternatives are there?

This question's answers provide a few examples, like walking the hierarchy at runtime or a mapping the addresses of objects to some larger information table, but the question is pretty C++ specific, although the answers are mostly not.

So, here is a language-agnostic (or so I hope) question:

What other ways of implementing virtual / dynamic dispatch are there other than vtables?

Note that this is not about trade-offs between speed, ease of implementation, code size, etc, though those would be very nice to have in the answers.

Community
  • 1
  • 1
Xeo
  • 129,499
  • 52
  • 291
  • 397
  • I don't think this is really language-agnostic. V-tables are perfect for C++, dispatcher for smalltalk, etc. It really depends on the language. – Pubby Nov 24 '11 at 05:27
  • 1
    Removed the extra tags as per http://meta.stackexchange.com/questions/113455/should-tags-thrown-in-for-publicity-be-removed – Billy ONeal Nov 24 '11 at 06:03
  • other language specific issues are related to how inheritance works, if the dispatch rules are based on one ore more dynamic types (SD vs MMD) etc. – riffraff Dec 01 '11 at 09:18

2 Answers2

8

Method 1: Flat VTable. All virtual methods of a class type (including inherited methods) are represented in a table of method pointers, one for each virtual method. Invocation requires calling indirect through the method pointer at a fixed offset in the table. Each new class creates its own vtable, copies the vtable of its ancestor, overwrites the pointers for virtual methods overriden in the class with pointers to the new methods, and adds new virtual methods defined in the class at the end of the table.

Method 2: Linked VTable (aka dynamic method table) Only the virtual methods declared or overridden in a class type occupy space in a linked vtable. Each method is assigned an id, and the id and method pointer are stored together in the dynamic method table. Invocation requires scanning the dynamic method table looking for a match for the virtual method id. If no match is found, the scan continues with the class's immediate ancestor's dynamic method table, and so on until either a match is found or you run out of ancestors.

Method 3: Message passing. No formal table of method pointers is generated by the compiler. Rather, each virtual method is assigned a unique id and invoked via a dispatch function. The dispatch function can be simply a case / switch statement on method ids. Case blocks may call individual methods of the object or may implement the behavior directly.

Dynamic method tables are actually a hybrid of traditional vtables and message passing. Pure message passing typically has little or no expectation of what the arguments are for the call. The Windows WndProc is an example of message passing, and replacing the wndproc pointer of a window handle is the means of hooking or overriding default behaviors. The WndProc has a fixed argument structure into which all messages must find a way to attach their specific parameter data.

The strength of message passing is flexibility, but often at a performance cost. VTable virtual methods are very fast to dispatch (simply a call indirect) but are very inflexible once established. Since each class VTable includes slots for all inherited virtual methods, VTables require more memory than dynamic method tables, especially in deep object hierarchies.

In the Delphi programming language, virtual methods are implemented using VTables, dynamic methods are implemented using dynamic method tables, and WndProcs use message passing.

dthorpe
  • 35,318
  • 5
  • 75
  • 119
0

I believe Python works like this: functions are first-class objects stored in an attribute table, just like any other member object owned by the class. When you call a function, the function is looked up in the attribute hash table and called. Overriding a method means simply replacing the function object with another function object with the same name.

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • 1
    Note that this is really the same as vtbls. – Billy ONeal Nov 24 '11 at 05:56
  • @BillyONeal, not at all. A Vtable is very static while an attribute list is completely dynamic. Also the lookup is by name(hash) and not by index. – Mark Ransom Nov 24 '11 at 05:59
  • 1
    Under the hood though, a vtbl and the attribute list are the same deal. They both end up being an indirect call. Sure, the attribute list can be reassigned inside the language; but the underlying concept is the same. – Billy ONeal Nov 24 '11 at 06:07
  • @BillyONeal, the question was about implementation details, not concepts. Are you claiming that an array and a hash table are exactly the same thing? – Mark Ransom Nov 25 '11 at 02:44