Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Pointer to base virtual function vs direct call of base virtual function

Why do these two behave differently?

(obj.*lpfn)();

vs

obj.Base::fn();

I know when we directly call virtual member function (obj.fn()) it will do a virtual dispatch(find correct ‘fn’ implementation for type of obj, and call it). But why does a pointer to member function call that is set to Base implementation((obj.*lpfn)()) lead to virtual dispatch, and why does the same expression, except directly called (obj.Base::fn()) not do virtual dispatch? If anything, I would expect them both to do call base implementation of Print function(no virtualization)

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

#include <iostream>
class Base {
public:
    virtual void Print() { std::cout << "Base::Print();\n"; }
};
class Derived : public Base {
public:
    void Print() override { std::cout << "Derived::Print();\n"; }
};
int main() {
    Derived d;
    auto lpfn = &Base::Print;
    (d.*lpfn)();
    d.Base::Print();
}

Output:

Derived::Print();
Base::Print();

>Solution :

From the C++ standard:

[expr.call]/1 For a call to a non-static member function, the postfix expression shall be an implicit (12.2.2, 12.2.3) or explicit class member access (8.2.5) whose id-expression is a function member name, or a pointer-to-member expression (8.5) selecting a function member; the call is as a member of the class object referred to by the object expression… If the selected function is non-virtual, or if the id-expression in the class member access expression is a qualified-id, that function is called. Otherwise, its final overrider (13.3) in the dynamic type of the object expression is called; such a call is referred to as a virtual function call.

Thus, there are only two cases where virtual dispatch is not performed for a call of a non-static member function: 1) the function is not virtual to begin with, or 2) the function is named with a qualified name, as in obj.Base::fn(). In all other cases – including the case of calling via a pointer-to-member – the final overrider is called.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading