Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Principle of virtual functions in C++

Tags:

c++

oop

I'm new to C++ and I just learned about virtual functions.

I heard that compiler makes a vtable, which contains the class's virtual functions address, when I define a virtual function. When a virtual function is called, the compiler find its address using the vtable.

I can't really understand the reason why compiler didn't call the function of the class instance that the object belongs to.

Why is the compiler using a vtable? Could you explain this?

like image 667
crazy_rudy Avatar asked Jul 16 '13 00:07

crazy_rudy


1 Answers

I can't really understand the reason why compiler didn't call a function of class instance belong?

That's what the compiler does - makes sure that your program calls the function of the class to which the instance belongs. The key word here is instance: the knowledge of the instance's class is not available at compile time.

Consider this simple example:

struct Dude {
    virtual void howdy() = 0;
};
struct Bob : public Dude {
    virtual void howdy() { cout << "Hi, Bob!" << endl; }
};
struct Moe : public Dude {
    virtual void howdy() { cout << "Hi, Moe!" << endl; }
};
// Note the pass by reference below: passing by reference or by pointer,
// but not by value, is important for achieving polymorphic behavior.
void say_hi(Dude& dude) {
    dude.howdy(); // <<== Here is the tricky line
}
int main(int argc, char* argv[]) {
    Bob b;
    Moe m;
    Dude *d = rand() & 1 ? (Dude*)&b : &m;
    say_hi(*d);
}

Note the tricky line: the compiler has the instance, but it does not know the class. Actually, it kind of knows the class, but not the most specific one. The knowledge the compiler has at compile time is sufficient to know that there is a function called howdy, but not sufficient to decide which one of several possibilities would be the one to call at runtime.

This is where vtables come to the rescue: the compiler knows that subclasses of Dude will have a pointer to their howdy function embedded somewhere into their vtable. That's all they need to know at compile time! They insert a virtual call that looks up the function pointer at runtime, achieving the behavior that you expect (the fancy word for that kind of behavior is "polymorphism"). Here is a demo of this program running on ideone.

like image 151
Sergey Kalinichenko Avatar answered Nov 11 '22 07:11

Sergey Kalinichenko