Is it possible in C++ to have a class override a virtual function, but only have virtual dispatch when the function is called through the superclass (ie. not when it is called on something statically typed as the subclass)? I know this isn’t what happens, but is there any way to achieve something close?
The reason for wanting this is that I have two classes which both expose a flush() function. The vast majority of the time in my program, I am calling flush() directly on a subclass object that I know the type of, so I don’t need virtual dispatch. However I want to add a superclass into the mix so that very infrequently I can pass a reference to an instance of either one of the classes into a doSomethingThenFlush() function, which would call flush() virtually.
I know I could use templates instead of virtual functions, and I know I could have two different functions (eg. flushVirtual() which just called flushNonVirtual(), and call flushNonVirtual() everywhere I don’t need virtual dispatch). But these both seem a bit like throwing code at a problem which is largely syntactical. Is there any more elegant way to achieve this?
Perhaps more importantly, does anyone know why virtualness is inherited in C++?
struct Base
{
virtual ~Base(){}
virtual void func();
};
struct Derived : public Base
{
void func(){}
};
void callVirtually(Base &base)
{
base.func();//this will use virtual dispatch
}
void callStatically(Derived &derived)
{
derived.func();//I don't want/need this to use virtual dispatch
}
int main()
{
Derived derived;
callVirtually(derived);
callStatically(derived);
}
In C++03, no.
As others said, it is a compiler optimization (and a frequently used one) to de-virtualize he call whenever it can assess that the runtime type of the object.
However, in C++0x we get two new keywords:
overrideandfinaland both can be applied to member functions (finalcan also be applied to a class).override: specify that this function overrides a virtual function in a base class, useful to get warned when this is not the casefinal: specify that this function (virtual) cannot be overriden in children classes.Your class would thus become:
Note: using final does not mandate that the compiler devirtualize function calls (from the Standard point of view), but any compiler worth its salt should do so.