inline virtual function
Asked Answered
K

3

26

In C++, my understanding is that virtual function can be inlined, but generally, the hint to inline is ignored. It seems that inline virtual functions do not make too much sense.

Is that right?

Can anybody give a case in which an inline virtual function is good?

Kingfish answered 25/1, 2010 at 4:38 Comment(5)
I don't see a real question here...Tedric
hi, what do you mean? I didn't address the problem clear? I am sorry about that.Kingfish
Inline functions are never necessary, so it's going to be hard to show you a necessary inline virtual one.Telegonus
to zneak: wow...that's true. Thanks so much.Kingfish
possible duplicate of Are inline virtual functions really a non-sense?Freedwoman
W
14

Under normal circumstances, a virtual function will be invoked via a pointer to a function (that's contained in the class' vtable). That being the case, a virtual function call can only be generated inline if the compiler can statically determine the actual type for which the function will be invoked, rather than just that it must be class X or something derived from X.

The primary time an inline virtual function makes sense is if you have a performance critical situation, and know that a class will frequently be used in a way that allows the compiler to determine the actual type statically (and at least one target compiler optimizes out the call via pointer).

Westfahl answered 25/1, 2010 at 4:47 Comment(5)
I also find very short functions to be clearer when they're inline in the class body.Harpp
The question addresses the keyword inline.Herculean
Also, I think if all your virtual function does is call some other function (which might happen with multiple inheritance, or for other reasons) the compiler can just put the thunking for that right in the vtable.Harpp
@gf, no, it addresses the concept of inlining a virtual function. Functions declared in the class body are implicitly declared to be inline, even without the inline keyword.Harpp
Fair enough, but its not necessarily meaning "inline in class body".Herculean
I
47

In order to answer this question fully, one needs to understand that the property of being virtual applies independently to the function itself and to the calls made to that function. There are virtual and non-virtual functions. There are virtual and non-virtual calls to these functions.

The same is true about the property of being inline. There are iniline and non-inline functions. And there are inlined and non-inlined calls to these functions.

These properties - virtual and inline - when applied to the function itself, do not conflict. They simply have no reason and no chance to conflict. The only thing that inline specifier changes for the function itself is that it modifies the One Definition Rule for that function: the function can be defined in multiple translation units (and it has to be defined in every translation unit where it is used). The only thing virtual specifier changes is that the class containing that function becomes polymorphic. It has no real effect on the function itself.

So, there's absolutely no problem in declaring a function virtual and inline at the same time. There's no basis for the conflict whatsoever. It is perfectly legal in C++ language.

struct S {
  virtual void foo(); 
};

inline void S::foo() // virtual inline function - OK, whatever
{
}

However, when people are asking this question, they are usually not interested in the properties of the function itself, but rather in characteristics of the calls made to the function.

The defining feature of a virtual call is that it is resolved at run time, meaning that it is generally impossible to inline true virtual calls:

S *s = new SomeType;
s->foo(); // virtual call, in general case cannot be inlined

However, if a call is by itself non-virtual (even though it goes to a virtual function), inlining is not a problem at all:

S *s = new SomeType;
s->S::foo(); // non-virtual call to a virtual function, can easily be inlined

Of course, in some cases an optimizing compiler might be able to figure out the target of a virtual call at compile time and inline even such virtual call. In some cases it is easy:

S ss;
ss.foo(); // formally a virtual call, but in practice it can easily be inlined

In some cases it is more complicated, but still doable:

S *s = new S;
s->foo(); // virtual call, but a clever compiler might be able
          // to figure out that it can be inlined
Illailladvised answered 25/1, 2010 at 6:5 Comment(9)
How can you say that ss.foo(); is formally a virtual call?Substrate
@Belloc: Because in C++ all calls to virtual functions are "virtual calls", i.e. resolved in accordance with the dynamic type of the object. Nothing in the language specification says that ss.foo() is somehow special or different. The only call where the "dynamic type" is ignored is a call with qualified name.Illailladvised
That's not what I can see here. The disassembly for the code shows that f->bar() is a virtual call, as expected, and d.bar() is a non-virtual call.Substrate
@Belloc: What you see in disassemly has no relevance at all. It simply means that your compiler optimized indirect call into a direct call, no more no less. Meanwhile, I talk about this call at language level. And at language level this is a virtual call.Illailladvised
I'm not an expert in gcc and clang, but as far as I can understand -O0 is the lowest optimization level for both compilers. By the way, you get the same result for clang with the switch -O0. Anyway, could you give me a quote from the Standard, confirming what you're saying?Substrate
@Belloc: There's no compiler setting that would be required disable all optimizations. Even in -O0 mode a lot of optimizing tricks will still be used by the compiler. As for the standard quote, it is right there in 5.2.2 Function call: "1 [...] 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 (10.3) in the dynamic type of the object expression is called; such a call is referred to as a virtual function call."Illailladvised
@Belloc: Moreover, on the second thougt, I woudn't even call it "optimization". True compiler optimizations occur when compiler generates code that deviates from the behavior of abstract C++ machine (still preseving observable behavior, of course). In this case there's no deviation. The call is resolved in accordance with the dynamic type of the object, exactly as the abstract C++ machine would do it. Whether the call is dispatched directly or indirectly (i.e. what you see in the disassembly) is completely inconsequential.Illailladvised
I have to leave now. I'll come back tomorrow. Thanks a lot for your attention in answering my comments.Substrate
You convinced me with [expr.call]/1. Again, thanks a lot (+1).Substrate
W
14

Under normal circumstances, a virtual function will be invoked via a pointer to a function (that's contained in the class' vtable). That being the case, a virtual function call can only be generated inline if the compiler can statically determine the actual type for which the function will be invoked, rather than just that it must be class X or something derived from X.

The primary time an inline virtual function makes sense is if you have a performance critical situation, and know that a class will frequently be used in a way that allows the compiler to determine the actual type statically (and at least one target compiler optimizes out the call via pointer).

Westfahl answered 25/1, 2010 at 4:47 Comment(5)
I also find very short functions to be clearer when they're inline in the class body.Harpp
The question addresses the keyword inline.Herculean
Also, I think if all your virtual function does is call some other function (which might happen with multiple inheritance, or for other reasons) the compiler can just put the thunking for that right in the vtable.Harpp
@gf, no, it addresses the concept of inlining a virtual function. Functions declared in the class body are implicitly declared to be inline, even without the inline keyword.Harpp
Fair enough, but its not necessarily meaning "inline in class body".Herculean
S
4

You can have virtual functions as inline. The decision to make the function call inline is not just made at the compile time. It could be anytime between compilation to rutime. You can refer to this article from Herb Sutter. Inline Redux

Stockroom answered 25/1, 2010 at 5:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.