Re: Virtual method inlining
On 7 nov, 07:50, Tobias M=FCller <trop...@bluewin.ch> wrote:
1 2 <s0s...@gmail.com> wrote:
On Nov 7, 5:06 am, Ian Collins <ian-n...@hotmail.com> wrote:
On 11/07/12 22:49, s0s...@gmail.com wrote:
I've heard of virtual method inlining in Java, and I'd like to know i=
f
the same is possible in C++. If so, in which cases is it applicable?
I ask because I'm learning Direct3D, and I want to know if it's OK to
use virtual methods for rendering operations that are performed at
every frame, or if I should give up virtual methods and just do all
rendering in a single file, of course at the expense of loss of abstr=
action.
** Please wrap your lines to something readable! **
The compiler may inline a virtual method if it knows the type of an
object. In the following trivial example, f.f() will probably be
inlined because the compiler knows that b is a B.
struct A
{
int n;
virtual void f() { n = 0; }
};
struct B : A
{
void f() { n = 10; }
};
int main()
{
B b;
b.f();
}
Well that's pretty much non-virtual method inlining, because B::f is
not virtual (even though A::f is),
B::f is implicitly virtual, if A::f is virtual.
not to mention that you're calling
it through a statically-known B instance.
That's the whole point.
Inlining means to copy the content of the called function into the callin=
g
function. For this to be possible, the content of the called funtion has =
to
be known statically.
In C++11, you can qualify a virtual method 'final'. That means it can be
inlined if it is called via a pointer of the same class:
struct A
{
virtual void f() { /* do stuff */ }
};
struct B : A
{
virtual void f() final { /* do other stuff */ }
};
void process(A* a)
{
a->f(); // cannot be inlined
}
void process(B* b)
{
b->f(); // can be inlined
}
In the code I'm writing, there are a lot of cases where the runtime
type is not known statically (after all, that's the whole point of
polymorphism).
OO-style runtime polymorphism is not the only type of polymorphism.
Polymorphism via templates is another possibility.
We are using a template based rendering library at work, that generates
performant code even if the rendering of every pixel is done in its own
function.
The library is highly polymorphic, but at compile time, not at runtime.
There are programming languages like Haskell, that rely almost exclusivel=
y
on compile time polymorphism. And Haskell still allows to write highly
generic/polymorphic code. Typical Haskell code is probably even more
generic than typical C++ code.
Thanks, very insightful!
I hadn't thought of using compile-time polymorphism, but that's
probably because I think the lack of method signatures is a bit of a
problem. For example, with runtime polymorphism, you might have
something like this:
class Shape
{
public:
virtual void Draw(int x, int y) = 0;
};
void DrawShape(Shape* s)
{
s->Draw(200, 100);
}
With compile-time polymorphism, you would have:
// Note: no Shape base class
template<class Shape>
void DrawShape(Shape* s)
{
s->Draw(200, 100);
}
It's not clear what operations the class supports, and what are the
parameter/return types of the methods. On the other hand, compile-time
polymorphism works nicely for things like STL iterators, where the
supported operations are clear from the nature of the object
(basically, iterators should behave as pointers).
P.S. didn't know about the "once virtual, always virtual" rule, even
after using C++ for so long!