10

I'm new so go easy on me :) From what my lecturer had told some time ago, the order of the virtual table is important. But I do not understand the reason for that!!?

Given the next code :

class A
{
public:
    A() {cout <<"1" << endl;};
    A (const A& s) {cout << "2" << endl;}
    ~A () {cout << "3" << endl;}
    void f1() {cout << "4" << endl; f2();}
    virtual void f2() = 0;
    virtual void f3() {cout << "5" << endl;}

};


class B : public A
{
public:
    B() {cout << "6" << endl;}
    B(const B& b) : A(b) {cout << "7" << endl;}
    ~B() {cout << "8" << endl;}

    virtual void f1() {cout<<"9"<<endl;}
    void f2() {cout<<"lO"<<endl; f4();}
    virtual void f2(int i) {cout << "11" << endl;}
    virtual void f4() {cout << "12" << endl; f3();}

};

He said that the order is :

A's vtable : 
A::f2()
A::f3()

B's vtable : 
B::f2()
A::f3()
B::f1()
B::f2(int)
B::f4()

But I don't understand why it is important? He said that the vtable is useless if it's not by its correct order, can you please explain why?

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
Ron_s
  • 1,429
  • 1
  • 14
  • 24

7 Answers7

18

There is no notion of vtables in the C++ standard. It's just that most implementations (if not all) use it for virtual dispatch. The exact conventions, however, are totally implementation-defined.

That said... The order of the functions is important, but not for the programmer, but for the compiler - you can arrange your functions however you want in your code. The compiler, however, will typically put each function pointer into a specific place in the vtable, which it has dedicated to that function. So that when it needs to call f() it knows the index of the f() function and takes that pointer from the vtable.

This question might help you as well: Virtual dispatch implementation details

Community
  • 1
  • 1
Armen Tsirunyan
  • 130,161
  • 59
  • 324
  • 434
9

The order of the vtable is important for things to work properly, but only to the compiler (i.e. you don't need to care because it takes care of it).

If the compiler put it out of order for itself, then yeah, things would break, because functions are looked up by offset (so an offset would yield a random function which would be catastrophic).But the average programmer doesn't need to worry about what order the vtable is in.

Seth Carnegie
  • 73,875
  • 22
  • 181
  • 249
8

It's only important when classes declare interfaces for external ABI (e.g. COM/XPCOM).

Most of the time it is not important and there is no reason to care about it.

hamstergene
  • 24,039
  • 5
  • 57
  • 72
  • 2
    +1 The only reason the vtable layout is standard on the Windows platform is because of COM. As a compiler vendor, if you want to support COM, you must follow Microsoft's implementation. However, more advanced features not used by COM, such as virtual inheritance, or multiple inheritance of non-interfaces, are implementation dependent. – Tamas Demjen Aug 26 '11 at 17:51
2

Every client of the vtable needs to know the correct order so that they can find the right method to call. But so long as all parties agree on the order, it doesn't matter what that order is.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
1

The vtable is a "look-up" table. It's basically a map of pointers to the class' virtual functions. If it's out of order, the pointers will point to the wrong functions. Bad things would happen if for example you wanted to call B:f1(), which takes no argument, but instead called B::f2(), which takes an int.

0

In visual studio, when you change the order of declarations for virtual functions, you may need to clean and rebuild the entire solution afterward.

My guess is that the vtable goes out of sync in particular cases.

So if things get wonky after making changes to your virtual functions, just recompiling may solve the issue.

0

I'm not sure about what he meant, but I'll try to explain how it works:

First of all, c++ defines the methods by name and signature. So when c++ initiates a class' virtual table it will replace all the base class' virtual functions with the derived virtual functions with the same name and signature.

When a class derives another class it's actually built over it. So the base class exists as part of the memory block (Complicated, read here - Virtual inheritance)

The virtual tables just hold a "pointer" to the right function depending on the type at run-time.

Community
  • 1
  • 1
Yochai Timmer
  • 48,127
  • 24
  • 147
  • 185