AdyAdy
AdyAdy

Reputation: 1028

C++ Virtual function called normally or virtually?

Let's say a virtual function is called on a derived class object (on the object normally or through pointer/reference) that overrides that function but none of its derived classes override it. Is it called "virtually" through v-pointer or as a normal function so all optimizations / inlining apply to it? Does the standard say anything about this?

class CBase{

public:
    virtual void doSomething() = 0;

};

class CDerived1 : public CBase{

public:
    void doSomething() override { /* do stuff */};

};

class CDerived2 : public CDerived1{


};

//...

CDerived1   derived1;
CDerived1*  p_derived1 = &derived1;

p_derived1->doSomething();

Upvotes: 3

Views: 84

Answers (1)

Nicol Bolas
Nicol Bolas

Reputation: 473212

Does the standard say anything about this?

No. Whether the call uses the dynamic dispatch mechanism or not is not observable behavior. And the standard only concerns itself with observable behavior.

How much compilers "devirtualize" virtual calls is ultimately implementation defined. If you just have T t; and you do t.whatever(), then you shouldn't use a compiler that cannot devirtualize that.

Inlining affects devirtualization as well. Given the T t declarations, if you pass a function a reference to this object, and it takes a T& parameter, calls into it can be devirtualized if that function gets inlined.

But if its a non-inlined instance of that function (say, a pointer to the function, perhaps through std::function or whatever), then devirtualization is much harder. See, the compiler doesn't see the whole program, so it cannot see if you have some class somewhere that inherits from T and overrides that method.

Only the linker, through whole program optimization, could possibly see all class definitions that inherit from it. And even then... maybe not. Because it is still technically possible for DLLs/SOs to inherit from classes. And the non-inlined function ought to be able to take those T&s and call their overridden methods.

So once you leave a chain of inlining where the object's dynamic type and virtual calls into it are both visible to the compiler, devirtualization becomes far more difficult if not impossible.

Upvotes: 4

Related Questions