I read that there is minor performance hit when calling virtual functions from derived classes if called repeatedly. One thing that I am not clear about is whether this affects function calls from the base class itself. If I call a method in the base class with the virtual keyword, does this performance hit still occur?
-
The performance hit happens anytime which function will be executed is not obvious during compilation. – Aug 05 '21 at 19:18
-
Yes, whenever virtual method is called a performance penalty is paid, unless the method is called non-virtually (with full class qualification or from constructor), the class which calls the method has the override marked `final` (or is `final` as a whole) or it is obvious to compiler which object `this` is pointing to (which would be a rare event). – SergeyA Aug 05 '21 at 19:20
-
2A key point is that this overhead only matters when it matters. – 500 - Internal Server Error Aug 05 '21 at 19:29
-
See this (possible duplicate) [question](https://stackoverflow.com/questions/449827/virtual-functions-and-performance-c), which has a number of links in the comments to other related questions. – 1201ProgramAlarm Aug 05 '21 at 19:52
4 Answers
If I call a method in the base class with the virtual keyword, does this performance hit still occur?
That the virtual function is being called from the base class will not prevent virtual lookup.
Consider this trivial example:
class Base
{
public:
virtual get_int() { return 1; }
void print_int()
{
// Calling a virtual function from the base class
std::cout << get_int();
}
};
class Derived : public Base
{
public:
virtual get_int() { return 2; }
};
int main()
{
Base().print_int();
Derived().print_int();
}
Is print_int()
guaranteed to print 1
? It is not.
That the function print_int()
exists in the base class does not prove that the object its called from is not derived.

- 59,987
- 13
- 123
- 180
-
This might be an issue for me as there is some aspect of time sensitivity. I would like to extend the functionality of the member functions of a class using a derived class. Is there any way to do this without the virtual keyword? – Peter Wang Aug 05 '21 at 20:47
-
1@PeterWang there are many ways to achieve polymorphism, with different tradeoffs. I encourage you to [ask a new question](https://stackoverflow.com/questions/ask) if you have a new question. – Drew Dormann Aug 05 '21 at 20:54
Yes, there will be a performance overhead.
This is due to the fact that virtual functions in an inheritance hierarchy may or may not be overloaded by any derived class.
This requires a lookup in a v-table, as the base class doesn't know any better as to which class is dynamically implementing the function.
Edit: As mentioned, there may be some optimization, but this shouldn't be relied on

- 1,218
- 1
- 13
- 28
-
1It's not *that* much of a hard rule though. There are a number of scenarios where devirtualisation can be performed, either during compilation or lto. As a simple example: https://gcc.godbolt.org/z/YacYacf6b – Aug 05 '21 at 19:37
Virtual functions are implemented by a virtual function table. Each class has a table of the virtual functions' addresses. An instance of a class with a virtual function table has a pointer to the table, which is set by the constructor.
When the code calls a regular function, its address is hard coded into it. When it calls a virtual function it has to calculate *(*vtbl + 8 * function-offset), which requires two memory accesses. That's the overhead, which can be avoided in cases mentioned by others above.
Point is, if the same function is called repeatedly, much of the overhead might be avoided. The first call would bring the virtual function table from RAM to the CPU's cache, meaning it would be as cheap as 1-2 CPU cycles to fetch again. Doing an integer shift and an addition is rather cheap. If the compiler knows its the same function of the same class, it could calculate it once and reuse the value.

- 435
- 1
- 3
- 15
Since the question is "Is there a performance hit?" and not "Can there be a performance hit?", it is surprisingly tricky to answer accurately. This is because compilers are given a lot of leeway when it comes time to optimize your code, and they often make use of it. The process of eliminating that specific overhead has a particular name: devirtualization.
Because of this, whether a cost is incurred or not will depend on:
- Which compiler is being used
- The compiler version
- The compiler settings
- The linker settings
- How the class is used
- Whether there are any subclasses that override the method.
So what should you do with so much uncertainty? Since the overhead is minor in the first place, the first thing is to not worry about it unless you need to improve performance in that specific area. Writing structurally sound and maintainable code trumps premature optimisation every single time.
But if you have to worry about it, then a good rule of thumb is that if you are calling a non-final virtual function from a pointer or reference (which includes this
) to a non-final class, then you should write code with the assumption that the tiny overhead associated with an indirect lookup through a vtable will be
paid.
That doesn't mean that the overhead will necessarily occur, just that there is a non-zero chance that it will be there.
So in your scenario, given:
class Base {
public:
virtual void foo() { std::cout << "foo is called\n"; }
void bar() { foo(); }
};
int main() {
Base b;
b.bar();
}
Base
is notfinal
Base::foo
is notfinal
.this
is a pointer.
So you should operate under the assumption that the overhead might be present, regardless of whether or not it ends up being there in the final built application.