There's no difference in the performance of a one-indirection lookup to find a virtual function to be called in the case of a two-levels inheritance derived class rather than a 40-levels inheritance derived class.
The reason is the following: each class holds a pointer to a virtual table which is used to resolve which function needs to be called for that specific object:
class Base
{
public:
virtual void function1() {};
virtual void function2() {};
};
class D1: public Base
{
public:
virtual void function1() {};
};
class D2: public Base
{
public:
virtual void function2() {};
};
the above code generates three virtual tables: one for objects of class Base
, one for objects of class D1
and one for objects of class D2
.
The important takeaway point here is that you don't need to traverse all virtual tables from the base up to find which function to call for a specific object:

in the diagram above you just
- Follow the
vptr
for your object (one indirection)
- Call the address of the function you're interested in
Modern compilers are able to optimize this process in the two points I listed above and except some particular cases this won't noticeably affect performances.
Credits: http://www.learncpp.com/cpp-tutorial/125-the-virtual-table/
Extra: as dyp noted, the "slow performances" of virtual functions usually refers to the fact that these functions cannot be inlined due to the vtable indirection. Whether that matters or not really boils down to the code and architecture you're dealing with (e.g. register pressure and other factors).