Can subclass inline a pure virtual method that is not inline in the base?
As I understand it, the compiler can inline a virtual function call when it knows at compile time what the type of the object will be at runtime (C++ faq).
What happens, however, when one is implementing a pure virtual method from a base class? Do the same rules apply? Will the following function call be inlined?
class base
{
public:
virtual void print() = 0;
virtual void callPrint()
{
print(); // will this be inline?
}
};
class child : public base
{
public:
void print() { cout << "hello\n"; }
};
int main()
开发者_StackOverflow{
child c;
c.callPrint();
return 0;
}
EDIT:
I think my original example code was actually a poor representation of what I wanted to ask. I've updated the code, but the question remains the same.
The compiler is never required to inline a function call. In this case, it is permitted to inline the function call, because it knows the concrete type of c
(since it is not indirected through a pointer or reference, the compiler can see where it was allocated as a child
). As such, the compiler knows which implementation of print()
is used, and can choose not to perform vtable indirection, and further choose to inline the implementation of the function.
However, the compiler is also free to not inline it; it might insert a direct call to child::print()
, or indirect through the vtable, if it decides to do so.
These optimizations in general boil down to the 'as-if' rule - the compiler must behave as-if it was doing a full vtable indirect - this means that the result must be the same, but the compiler can choose a different method of achieving the result if the result is the same. This includes inlining, etc.
The answer is of course "it depends", but in principle there's no obstruction to optimization. In fact, you're not even doing anything polymorphic here, so this is really straight-forward.
The question would be more interesting if you had code like this:
child c;
base & b = c;
b.print();
The point is that the compiler knows at this point what the ultimate target of the dynamic dispatch will be (namly child::print()
), so this is eligible for optimization. (There are two separate opportunities for optimization, of course: one by avoiding the dynamic dispatch, and one coming from having the function body of the target visible in the TU.)
There are only a couple of rules you should be aware of:
1) The compiler is never forced to inline - even using the directive or defining a method in the header.
2) Polymorphism MUST ALWAYS WORK. This means that the compiler will prefer calling the function via the vftable rather than inlining it when the possibility of dynamic calls exists.
精彩评论