Polymorphism is the reason virtual methods exist. The ability to separate interface from implementation can reduce program complexity greatly; but at a cost. Every type that uses virtual methods must have a vtable, and every object of that type must have a pointer to this vtable. In and of itself this isn't a huge cost. However, a poorly chosen object hierarchy can introduce hidden bloat.
I've seen projects were more then a meg of memory was wasted on these hidden vtables. This might not sound like a lot, but on an embedded system it matters.
There is also a runtime cost, as the method pointer is looked up in the v-table. With modern CPU caching this isn't really a big deal, but again, embedded system caches are usually very small.
There is a little trick that can eliminate these problems, with some caveats. It uses the curiously recurring template pattern.
Here's a class "A" that calls dispatches foo to whatever its template argument is.
Here's two sub-classes of A, B & C.template < class D >
class A
{public:
void foo()
{
static_cast<D*>(this)->foo();
}
};
Notice how both these classes supply themselves as the template argument for A.class B : public A<B>
{public:
void foo()
{
printf("B::foon");
}
};
class C : public A<C>
{public:
void foo()
{
printf("C::foon");
}
};
Here's a function which calls foo on its argument.
Now when you run call_foo, on an object of type B or C, you'll get polymorphic behavior. Try it.template< class D >
void call_foo( A<D>& a )
{a.foo();
}
This will effectively give you polymorphism without a v-table and without the run-time dispatch overhead. There are some caveats though. Because templates are evaluated at compile time, the compiler has to infer exactly what type something is so it knows which version of foo is invoked. This prevents doing things like putting B's and C's into the same collection.int main()
{B b;
C c;
call_foo( b );
call_foo( c );
return 0;
}
Overall it's a handy trick that's used in many modern C++ api's. For example Microsoft's WFC API & Boost.