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);
}
It is not mandatory for the derived class to override (or re-define the virtual function), in that case, the base class version of the function is used. A class may have virtual destructor but it cannot have a virtual constructor.
Yes, Its correct that a Derived class has to OVERRIDE the function which is Pure Virtual in the Parent Class.
Adding the "virtual" keyword is good practice as it improves readability , but it is not necessary. Functions declared virtual in the base class, and having the same signature in the derived classes are considered "virtual" by default.
A virtual function is a member function that you expect to be redefined in derived classes. When you refer to a derived class object using a pointer or a reference to the base class, you can call a virtual function for that object and execute the derived class's version of the function.
Virtualness is inherited because you don't know if someone is going to derive further from your Derived
. Someone could just as well make a MoreDerived
which could be passed to a function expecting a Derived&
, and they'd be sad when they found that it was Derived
's versions of all your virtual functions were bieng called instead of MoreDerived
's.
If you mean that you won't ever inherit from Derived
so you don't want to pay for a virtual function call, then you're out of luck, because C++ provides no way to promise that you won't ever inherit from a class, which would be necessary to do what you are wanting.
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: override
and final
and both can be applied to member functions (final
can 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:
struct Derived : public Base
{
void func() final {}
};
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.
In your specific example, if callStatically
gets inlined, the compiler will probably avoid the virtual function dispatch because it can see the object's actual type (because it is a local variable).
Probably your compiler can also avoid a virtual dispatch for cases like this:
class Foo {
public:
callStatically() { d.func() }
private:
Derived d;
};
The compiler is likely to perform this optimization whether or not callStatically
is inlined, because it can see the actual type of the variable member.
But to my knowledge, there is no way to force the compiler to bypass the virtual call in general.
The answer lies in your question.
derived.func(); // no virtual dispatch
When you call a virtual
function using object, there is no virtual
dispatch. It calls the function using the static-type of the object.
virtual
function comes into the picture only when you try to call a function using a pointer or a reference.
Edit: In your updated question, you are using Derived&
to call func()
. Calling by reference will make sure that virtual
dispatch happens. So there is no language facility (like final
in Java), which will stop virtual
dispatch.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With