views:

402

answers:

11

Why, for example, is there no language support to examine a vtable? Why can't I replace a member function with a new one? I have a gut feeling that there are ways to put such features to good use.

Are there any other languages out there which allow me to do such things?

+17  A: 

Because it is an implementation detail of the compiler. That implementation may change, and any code that relies on it would be fragile at best.

Ed Swangren
+8  A: 

C++ is a language where you never 'pay for' what you don't use. This kind of runtime support would run contrary to that philosophy.

There are plenty of languages (on the more dynamic end of the spectrum) that support that.

Brian
Could you please name some languages that support this. Voice in my head says JavaScript and Python... but not sure really.
Vulcan Eager
I don't know specifically whether it's supported by JavaScript or Python, but it is most definitely supported by Ruby.
Mikael Auno
For a really powerful object system look up 'CLOS' and 'MOP'.
gimpf
Javascript, Python, Ruby, Lisp — you can pretty much pick any dynamic language and it will have it.
Chuck
+8  A: 

Because it doesn't have to be implemented as a VTable, although this is usually the case. In short, there is no such thing as VTable in C++!

AraK
+3  A: 

JavaScript, Python, and Ruby can all do this. In those languages, class and instance definitions are mutable at runtime. Abstractly, each object and type is a dictionary of member variables and methods that can be examined and updated.

This isn't possible in C++ because it would require being able to rewrite generated binary code, which can carry a substantial performance cost.

Novelocrat
+2  A: 

I believe you can do things like that in dynamic languages like Python:

>>> class X():
...     def bar(self): print "bar"
...     
>>> x = X()
>>> x.bar()
bar
>>> def foo(x): print "foo"
... 
>>> X.bar = foo
>>> x.bar()
foo

The difference with a static language like C++ is that the interpreter looks up all names at runtime and then decides what to do.

In C++ there are likely other solutions to the "replace a member function with another" problem, the simplest of which might be using function pointers:

#include <iostream>

class X;
typedef void (*foo_func)(const X&);

void foo(const X&) { std::cout << "foo\n"; }
void bar(const X&) { std::cout << "bar\n"; }

class X
{
    foo_func f;
public:
    X(): f(foo) {}
    void foobar() { f(*this); }
    void switch_function(foo_func new_foo) { f = new_foo; }
};

int main()
{
    X x;
    x.foobar();
    x.switch_function(bar);
    x.foobar();
}

(foo and bar don't use the X& argument, in this example, similar to the Python example)

UncleBens
+1  A: 

I am working on a statically compiled language that exposes the vtable, and believe me it is quite a bit of hair to expose.

Joshua
+3  A: 

Vtables only exist in certain circumstances in some compilers (i.e. they are not specified in the standard but an implementation detail). Even when they do exist, they only occur when you have virtual functions and need the indirection to implement polymorphism. When this is not required they can be optimised out, saving the overhead of the indirection on the call.

Sadly (or otherwise, depending on your views on the matter ;-), C++ was not designed to support monkey patching. In some cases (e.g. COM) the vtable is a part of the implementation and you might be able to poke about behind the scenes. However, this would never be supported or portable.

ConcernedOfTunbridgeWells
+1  A: 
  • Anything you can do in C++, you can do in straight C with a little elbow grease.
  • Any modest and reasonable C program should compile in C++.

Maybe what you want is to implement your own vtables without using C++'s built-in facility. You will have a lot of fun with pointer-to-member-functions (ptmf's)!

You will have trouble finding a compiled language with vtable introspection because there's little demand and it's not easy to implement. For interpreted languages, though, the situation is the other way around.

Potatoswatter
A: 

As others have pointed out, there is no concept of "vtable" in the C++ standard, as it's just a nearly universal implementation technique, much like name mangling.

If you're looking for being able to redefine functions on the fly in a compiled language, you might be interested in Common Lisp. There have got to be others, but the only other languages I can think of either have static inheritance and functions or are interpreted at a large cost in performance.

David Thornley
+1  A: 

Are there any other languages out there which allow me to do such things?

Objective-C (and Objective-C++ as well) allows the runtime replacement of already compiled methods. It's either the best combination of static and dynamic techniques or the worst, depending on who you ask.

ergosys
+4  A: 

The main reason is that keeping vtable as an implementation detail allows any concrete implementation to optimize it as it sees fit; this means that it can e.g. trim or even eliminate vtable altogether if it can prove that there are no virtual calls for a given method (or all methods). Or it may replace a vtable dispatch with an if-else type check if e.g. it sees that there are only a few alternatives (this can be advantageous because branch prediction will work in this case, but not with vtables, and also because if-else branches can then be inlined). It can reorder methods in vtable such that most commonly called ones come earlier, or such that those that are commonly called one right after another fill adjacent slots in vtable to take advantage of caching. And so on, and so forth. Of course, all those implementations would also make vtable layout entirely unpredictable, and thus useless, if it were to be exposed (by the language spec) to implementation.

As well, vtables aren't as simple as they sound to be. For example, compilers often have to generate thunks to fix-up this pointer for things such virtual inheritance, or multiple inheritance combined with covariant return types. This is again something that doesn't have a "single best way" to do it (which is why different compilers do it differently), and standardizing it would effectively require settling on a particular way.

That said, "vtable switching" is a potentially useful technique if exposed as a higher-level construct (so that optimizations are still possible). For an example, see UnrealScript, which allows one to define several states for a class (one default, other named), and override some methods in named states. Derived classes can override more methods in existing states, or add their own states and override in them. Furthermore, states can extend other states (so if a method isn't overridden for a particular state, it falls back to the "parent" state, and so on until the chain reaches the default state). For actor modelling (which games essentially are) this all makes a lot of sense, which is why UnrealScript has it. And the obvious efficient implementation mechanism for all of this is vtable switching, with each state having a separate vtable.

Pavel Minaev