Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Will a method be called virtually even if no sub-class overrides it?

Tags:

c++

virtual

call

Imagine you have the following classes:

class A {
  public:
    virtual void print()           { printf("A\n"); }
};
class B : public A {
  public:
    virtual void print() override  { printf("B\n"); }
};
class C : public B {
    // no override of print
};

And now if you create an instance of B and call print:

B * b = new B;
b->print();

Will this method be called virtually? In other words, will the exact method to be called determined at compile-time or run-time?

Theoretically it can be determined at compile-time, because we know, that none of sub-classes of B overrides that method, so no matter what I assign into pointer to B B * b = new C; b->print();, it will always call B::print().

Does the compiler know it too and save me from unnecessary overhead of the virtual call?

like image 816
Youda008 Avatar asked Apr 11 '16 18:04

Youda008


People also ask

Does a virtual method have to be overridden?

When the method is declared as virtual in a base class, and the same definition exists in a derived class, there is no need for override, but a different definition will only work if the method is overridden in the derived class. Two important rules: By default, methods are non-virtual, and they cannot be overridden.

Can we override non-virtual method in Java?

You can override any method of a class, the question is really how to access the non-virtual method, or should I have made the method virtual in the first place. With a virtual method, you always access the overridden method regardless of the class variable used to reference it.

Can you override without virtual C++?

New! Save questions or answers and organize your favorite content. Learn more.

Do all virtual methods have to be implemented?

Only the pure virtual methods have to be implemented in derived classes, but you still need a definition (and not just a declaration) of the other virtual methods. If you don't supply one, the linker might very well complain.


2 Answers

Theoretically it can be determined at compile-time, because we know, that none of sub-classes of B overrides that method

You cannot determine this at compile time in general case, because C++ compiler deals with one translation unit at a time. A class from a different translation unit, say, class D : public B could override the method. However, the compiler may have no visibility into the translation unit of class D at the time the call to b->print() is translated, so the compiler must assume a virtual call.

In order to address this shortcoming C++11 introduced final keyword, which lets programmers tell the compiler that there would be no further overrides down from this level of inheritance hierarchy. Now the compiler can optimize out the virtual call, and also enforce the requirement of no further overrides.

like image 139
Sergey Kalinichenko Avatar answered Oct 15 '22 12:10

Sergey Kalinichenko


Regarding

Theoretically it can be determined at compile-time, because we know, that none of sub-classes of B overrides that method, so no matter what i assign into pointer to B B * b = new C; b->print();, it will always call B::print().

Yes.

However, whether the compiler will do this optimization depends entirely on the compiler, what it knows, and what you tell it to do.

What the compiler knows depends on many factors, such as

  • Are there classes defined in multiple translation units that are compiled separately?

  • Are you using global optimization?

  • Are you perhaps using the keyword final to inform the compiler?

With your specific example,

B * b = new B;
b->print();

where print is virtual, I would feel pretty confident that it would be called non-virtually regardless of compiler, because here the compiler knows what b refers to. Let's check.

OK, with MinGW g++ 5.1 and option -O2 (I didn't try anything else) the call is compiled down to a direct call of puts, even bypassing the printf.

like image 43
Cheers and hth. - Alf Avatar answered Oct 15 '22 12:10

Cheers and hth. - Alf