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?
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
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).
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
Related
Can someone explain the below paragraph please, no explanation is given:
The reason it works is that, in virtually all implementations of C++,
virtual functions are implemented with a "virtual function table",
which is an array of pointers to functions. This is incompatible
with function inlining because you simply can't have a pointer to
inline code. Thus for most situations, virtual and inline are incompatible; the compiler
will simply ignore the inline statement. However, there is one situation whereby they are
compatible: where the object is accessed directly instead of through a pointer.
"High Performance Game Programming in C++", Paul Pedriana
Can someone please explain why the two sentences in bold are so?
It simply means the compiler won't inline a call it has to resolve at run-time.
Suppose you have
struct A
{
virtual void foo() {};
};
and
void test(A* a)
{
a->foo();
}
This call is resolved at runtime. Since foo() could have been overriden by a deriving class and a could point to an object of a derived type, a->foo() can't be inlined - it will be resolved by a lookup.
The second statement means that virtual functions could be inlined in some situations:
void test(A a)
{
a.foo();
}
In this case, a is of type A (even if the original object passed to the function was a derived type, it was sliced because you passed by value) - the call is guaranteed to call A::foo so it can be inlined by the compiler.
First, the keywords aren't incompatible in any way. The paragraph is discussing the underlying implementation. A particular function call may be either inlined or go through a virtual dispatch, but usually not both. To understand why, you just need to understand what an inline call or a virtual call is.
An inlined function call is one where at least part of the called function is spliced directly into the calling function. This is a low-level optimization that the compiler may perform even on functions that aren't defined as inline. But in the early days when compilers were dumber and executable code size was more important, the keyword was more directly related to the optimization feature.
A virtual call is one where the caller doesn't know exactly what function will be executed. The function's implementation needs to be looked up (dispatched) according to the class at runtime.
So if the function will only be determined at runtime, the compiler cannot splice two functions together. It doesn't know what function would get spliced in.
But you can call a virtual function without making a special dispatch. This occurs if the compiler can be sure of the object's actual type at compile time. For example, if dog is derived from pet with a virtual method speak,
dog fido;
fido.speak(); // direct dispatch: we know fido is a dog.
But this is not the case if we have a reference:
bird buddy;
pet &favorite = prefer_dogs? fido : buddy;
favorite.speak(); // favorite may be a bird or dog: need virtual dispatch
Most of the time, when you call a virtual function you do so through a virtual dispatch.
There is another case, which as far as I know is only theoretical: if the compiler can be sure of the whole class hierarchy (or the choices in a given instance), it could add a Boolean test whether favorite is a bird or a dog and inline both function calls as alternatives in an automatically-generated if … else statement. But anyway, this is just nuts and bolts that you shouldn't worry about.
What's important is that a virtual function is called according to the type the object was defined as, and an inline function may be defined in a header file. And that's all that matters.
It is not "incompatible", just when actually virtual call is placed it is impossible to inline the unknown code. When static call is made to the function inlining will work alright.
The text is not very well formed, but if you already know what it wants to tell, you can find it there. ;-)
Can I change a pure-virtual function (in a base class) to become non-pure without running into any binary compatibility issues? (Linux, GCC 4.1)
thanks
There is no compatibility issues when you switch from pure virtual to virtual and then re-compile the code. (However, virtual to pure virtual may cause problems.)
The only thing you should take care is, that the non-pure virtual methods must have a body. They cannot remain unimplemented. i.e.
class A {
public:
virtual int foo ()
{
return 0; //put some content
}
};
You cannot simply put like,
virtual int foo();
It will cause linker error, even if you don't use it.
What does it mean to maintain binary compatibility to you?
The object layout will be the same, but you will be breaking the One Definition Rule unless you recompile all code, at which point binary compatibility is basically useless. Without recompiling, then the ODR is broken, and while it might be the case that it works, it might also not work.
In particular if all of the virtual methods in the class are either pure or defined inline, then the compiler might generate the vtable in each translation unit that includes the header and mark it as a weak symbol. Then the linker will pick one of them and discard all the others. In this situation the linker is not required to verify that all of the vtables are exactly the same and will pick one at random (or deterministically in an undefined way), and it might pick one such vtable where the method is pure virtual, which in turn might end up crashing the application if the method is called on an object of the base class.
From Addison Wesley: C++ Templates
Member function templates cannot be
declared virtual. This constraint is
imposed because the usual
implementation of the virtual function
call mechanism uses a fixed-size table
with one entry per virtual function.
However, the number of instantiations
of a member function template is not
fixed until the entire program has
been translated.
Does the above quote mean that templates have static binding and virtual functions have dynamic binding, that's the reason there cannot be virtual function templates? Please see if a explanation in layman's language is possible.
Yes, and no.
The most popular method to resolve virtual function calls is to use a table ("vtable"), where each virtual function maps to an index in the table. This more or less requires that you know the size of the table.
With templates, new functions will be created as needed in different modules. You would then either have to convince the linker to build the table after figuring out the final number of functions, or use some kind of runtime structure to search for available functions at runtime.
On many systems, the linker is part of the OS and knows nothing about C++, so that option is limited. A runtime search would of course affect the performance negatively, perhaps for all virtual functions.
So, in the end, it was decided that it just was not worth the trouble of introducing virtual templates into the language.
Consider:
struct X
{
template <typename T>
T incr(const T& t)
{
return t + 1;
}
};
As incr() is applied to different T types, new functions are generated. Say inside app.c++ you have:
X x;
x.incr(7); // incr<int>()
x.incr(7.0); // incr<double>()
x.incr("hello"); // incr<const char*>()
Then as it's compiling app.c++, it sees 3 functions that - if incr were allowed to be virtual - it could make space for the three instantiations above in the virtual dispatch table for X. Then say it loads a shared library at run-time, and the code for that library had 2 instantations of X::incr for uint32_t and std::string::const_iterator. dlopen() would need to grow the existing virtual dispatch table for the already created objects to make space for two new functions. Doesn't sound too horrible, but consider:
each bit of code calling virtual functions must know if the address of those functions was bumped along by some offset at run-time (due to dynamic loading of extra instantiations), so there's extra memory and performance cost in every virtual dispatch
when there's multiple inheritance, or a derived class is itself derived from, the compiler may want to create a single virtual dispatch table for the total set of virtual functions (one option, there are many for implementing virtual dispatch): in this case, the new virtual functions would either displace other classes' virtual functions or need to be disjoint from the existing ones. Again, more run-time overheads in any scheme to manage this.
So, the very rare occasions when this might be useful aren't worth compromising and complicating the more common case of non-templated virtuals.
Does the above quote mean that templates have static binding and virtual functions have dynamic binding, that's the reason there cannot be virtual function templates?
Basically, yes. More specifically, the static binding causes a problem when the code is being generated to support dynamic binding.
When the compiler compiles the base class, it finds a virtual function and decides to make a virtual function table - this will be used to implement dynamic binding: when a virtual function is called on a derived instance, the compiled code follows a pointer in the instance to the virtual function table for the derived class, then a pointer in that table to the implementation of the virtual function. This table has to include every possible virtual function that could be called. Now, suppose we made a templated virtual function. The function table would need an entry for every instantiation of the template, because any of those functions could conceivably be called at runtime. But the information about what types the template is instantiated with, cannot (in general) be gathered at the time that the virtual function table is generated. (At least, not without playing around with the C++ compilation model.)
virtual functions and templates still work fine together, there is just a small special case which is not implmented.
template<class T>
class A { virtual void f()=0; }; // works fine
class A { template<class T> virtual void f(T t)=0; }; // does not work
Depends on what you mean by binding.
You can implement a virtual method by calling a member template. As long as you inline it, any compiler with tail-call optimization will eliminate the overhead
Sorta.
You can't really "override" an uninstantiated template because it doesn't even exist in the compiled application. If you instantiate it, then you're not overriding a template, but just another ordinary function. :-)
guys. I have read several threads about the interaction between inline and virtual co-existing in one function. In most cases, compilers won't consider it as inline. However, is the principle applied to the scenario when a non-virtual inline member function call a virtual function? say:
class ABC{
public:
void callVirtual(){IAmVitrual();}
protected:
virtual void IAmVirtual();
};
What principle? I would expect the compiler to generate a call to the virtual function. The call (in effect a jump-to-function-pointer) may be inlined but the IAmVirtual function is not.
The virtual function itself is not inline, and it is not called with qualification needed to inline it even if it were, so it can't be inlined.
The whole point of virtual functions is that the compiler generally doesn't know which of the derived class implementations will be needed at run-time, or even if extra derived classes will be dynamically loaded from shared libraries. So, in general, it's impossible to inline. The one case that the compiler can inline is when it happens to know for sure which type it's dealing with because it can see the concrete type in the code and soon afterwards - with no chance of the type having changed - see the call to the virtual function. Even then, it's not required to try to optimise or inline, it's just the only case where it's even possible.
You shouldn't try to fight this unless the profiler's proven the virtual calls are killing you. Then, first try to group a bunch of operations so one virtual call can do more work for you. If virtual dispatch is still just too slow, consider maintaining some kind of discriminated union: it's a lot less flexible and cleanly extensible, but can avoid the virtual function call overheads and allow inlining.
All that assumes you really need dynamic dispatch: some programmers and systems over-use virtual functions just because OO was the in thing 20 years ago, or they've used an OO-only language like Java. C++ has a rich selection of compile-time polymorphic mechanisms, including templates.
In your case callVirtual() will be inlined. Any non-virtual function can be a good candidate of being inline (obviously last decision is upto compiler).
Virtual functions have to be looked up in the Virtual Method Table, and as a result the compiler cannot simply move them to be inline. This is generally a runtime look up. An inline function however may call a virtual one and the compiler can put that call (the code to look up the call in the VMT) inline.
In particular, wouldn't there have to be some kind of function pointer in place anyway?
I think that the phrase "classes with virtual functions are implemented with vtables" is misleading you.
The phrase makes it sound like classes with virtual functions are implemented "in way A" and classes without virtual functions are implemented "in way B".
In reality, classes with virtual functions, in addition to being implemented as classes are, they also have a vtable. Another way to see it is that "'vtables' implement the 'virtual function' part of a class".
More details on how they both work:
All classes (with virtual or non-virtual methods) are structs. The only difference between a struct and a class in C++ is that, by default, members are public in structs and private in classes. Because of that, I'll use the term class here to refer to both structs and classes. Remember, they are almost synonyms!
Data Members
Classes are (as are structs) just blocks of contiguous memory where each member is stored in sequence. Note that some times there will be gaps between members for CPU architectural reasons, so the block can be larger than the sum of its parts.
Methods
Methods or "member functions" are an illusion. In reality, there is no such thing as a "member function". A function is always just a sequence of machine code instructions stored somewhere in memory. To make a call, the processor jumps to that position of memory and starts executing. You could say that all methods and functions are 'global', and any indication of the contrary is a convenient illusion enforced by the compiler.
Obviously, a method acts like it belongs to a specific object, so clearly there is more going on. To tie a particular call of a method (a function) to a specific object, every member method has a hidden argument that is a pointer to the object in question. The member is hidden in that you don't add it to your C++ code yourself, but there is nothing magical about it -- it's very real. When you say this:
void CMyThingy::DoSomething(int arg);
{
// do something
}
The compiler really does this:
void CMyThingy_DoSomething(CMyThingy* this, int arg)
{
/do something
}
Finally, when you write this:
myObj.doSomething(aValue);
the compiler says:
CMyThingy_DoSomething(&myObj, aValue);
No need for function pointers anywhere! The compiler knows already which method you are calling so it calls it directly.
Static methods are even simpler. They don't have a this pointer, so they are implemented exactly as you write them.
That's is! The rest is just convenient syntax sugaring: The compiler knows which class a method belongs to, so it makes sure it doesn't let you call the function without specifying which one. It also uses that knowledge to translates myItem to this->myItem when it's unambiguous to do so.
(yeah, that's right: member access in a method is always done indirectly via a pointer, even if you don't see one)
(Edit: Removed last sentence and posted separately so it can be criticized separately)
Non virtual member functions are really just a syntactic sugar as they are almost like an ordinary function but with access checking and an implicit object parameter.
struct A
{
void foo ();
void bar () const;
};
is basically the same as:
struct A
{
};
void foo (A * this);
void bar (A const * this);
The vtable is needed so that we call the right function for our specific object instance. For example, if we have:
struct A
{
virtual void foo ();
};
The implementation of 'foo' might approximate to something like:
void foo (A * this) {
void (*realFoo)(A *) = lookupVtable (this->vtable, "foo");
(realFoo)(this); // Make the call to the most derived version of 'foo'
}
The virtual methods are required when you want to use polymorphism. The virtual modifier puts the method in the VMT for late binding and then at runtime is decided which method from which class is executed.
If the method is not virtual - it is decided at compile time from which class instance will it be executed.
Function pointers are used mostly for callbacks.
If a class with a virtual function is implemented with a vtable, then a class with no virtual function is implemented without a vtable.
A vtable contains the function pointers needed to dispatch a call to the appropriate method. If the method isn't virtual, the call goes to the class's known type, and no indirection is needed.
For a non-virtual method the compiler can generate a normal function invocation (e.g., CALL to a particular address with this pointer passed as a parameter) or even inline it. For a virtual function, the compiler doesn't usually know at compile time at which address to invoke the code, therefore it generates code that looks up the address in the vtable at runtime and then invokes the method. True, even for virtual functions the compiler can sometimes correctly resolve the right code at compile time (e.g., methods on local variables invoked without a pointer/reference).
(I pulled this section from my original answer so that it can be criticized separately. It is a lot more concise and to the point of your question, so in a way it's a much better answer)
No, there are no function pointers; instead, the compiler turns the problem inside-out.
The compiler calls a global function with a pointer to the object instead of calling some pointed-to function inside the object
Why? Because it's usually a lot more efficient that way. Indirect calls are expensive instructions.
There's no need for function pointers as it cant change during the runtime.
Branches are generated directly to the compiled code for the methods; just like if you have functions that aren't in a class at all, branches are generated straight to them.
The compiler/linker links directly which methods will be invoked. No need for a vtable indirection. BTW, what does that have to do with "stack vs. heap"?