Public Group

# [C++] When you inherit from a base class which has virtual functions, why is the overrided functions in the derived class virtual as well.

This topic is 2779 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

So for example,
 struct IRun{ virtual void run()const{ /*...*/} }; struct FastRunner: IRun{ //I was told that FastRunner::run is by default virtual now void run()const{ /* ... /*} //so that the above run function is the same as the one below //virtual void run()const{/*.../*} }; 

Why does FastRunner::run() has to be virtual?

##### Share on other sites
Because virtual means "call the right version of this function for the class it was defined in". If it was non-virtual the virtual keyword in the base class wouldn't mean anything.

##### Share on other sites

Because virtual means "call the right version of this function for the class it was defined in". If it was non-virtual the virtual keyword in the base class wouldn't mean anything.

I get why the virtual keyword has to be there in the base class, but why is the derived function labeled virtual as well by default?

##### Share on other sites
If you derive from the FastRunner class it makes sense for the run function to continue to be virtual.

Also, I don't think it's virtual by default, Its virtual by force. I don't think you can "stop" the chaining of a virtual function in C++

##### Share on other sites
It is forced virtual, and cannot be undone.

Why don’t you try asking the opposite question?
What if it could be non-virtual? Exactly what behavior would you expect, and how would it fit in with the “intentions” behind virtual overriding?

L. Spiro

##### Share on other sites

It is forced virtual, and cannot be undone.

Why don’t you try asking the opposite question?
What if it could be non-virtual? Exactly what behavior would you expect, and how would it fit in with the “intentions” behind virtual overriding?

L. Spiro

Using the example above, I would think that there is no need fo FastRunner::run to be virtual because( assuming vtable implementation ), the vtable only needs the address of FastRunner::run. Conceptually, I don't think it makes sense for FastRunner::run to be labeled virtual as well because when something is labeled virtual I would expect it to be overridden by a derived class. Wouldn't it be enough to just label IRun::run as virtual ?

##### Share on other sites
Coming from a C background, I think of member functions as functions that take a first argument that is a pointer to the object (called `this'), and I think of virtual functions as pretty much pointers to member functions. This analogy doesn't always work, but it's a reasonable first approximation, and I use virtual functions about as often as I used to use function pointers in C (i.e., very rarely), and for about the same things (e.g., to associate an action with clicking on a menu entry). With this picture in mind, the rule "once virtual, always virtual" makes perfect sense to me.

##### Share on other sites

[quote name='YogurtEmperor' timestamp='1330795440' post='4918902']
It is forced virtual, and cannot be undone.

Why don’t you try asking the opposite question?
What if it could be non-virtual? Exactly what behavior would you expect, and how would it fit in with the “intentions” behind virtual overriding?

L. Spiro

Using the example above, I would think that there is no need fo FastRunner::run to be virtual because( assuming vtable implementation ), the vtable only needs the address of FastRunner::run. Conceptually, I don't think it makes sense for FastRunner::run to be labeled virtual as well because when something is labeled virtual I would expect it to be overridden by a derived class. Wouldn't it be enough to just label IRun::run as virtual ?
[/quote]
I disagree. I think it would make more sense if FastRunner::run had to be labeled virtual, because it is virtual. And anyone deriving a class with a run function would know that run was virtual.

I may be confused here but it seems to me that you argue that the last run function in the vtable doesn't have to be virtual because it is the last one in the table.
If that is the case, you are wrong, because I want to derive a new class from FastRunner in a couple of years from now, and when I do, FastRunner::run will no longer be the last address in the vtable.

##### Share on other sites

I disagree. I think it would make more sense if FastRunner::run had to be labeled virtual, because it is virtual.
[/quote]
Thats a weird circular way to counter an argument? Its not really virtual is it? Its more like its overriding a virtual function.

And anyone deriving a class with a run function would know that run was virtual.
[/quote]

Yes IRun::run is virtual and that makes sense, but IFastRunner::run doesn't really have to be virtual does it? It being virtual tells me that some other class might derive from FastRunner::run. I think one should instead have an option to explicitly state it as virtual.

I may be confused here but it seems to me that you argue that the last run function in the vtable doesn't have to be virtual because it is the last one in the table.
[/quote]
No that is not what I was saying.

Idk, maybe its there for efficiency reasons. Or that I'm just confused somehow and not seeing the reason for FastRunner::run to be explicitly virtual. Hope my question is clear

##### Share on other sites
Let me put it another way.

I hold an array of CEntity *’s. I don’t know if those objects are actually CActors, CWorldObjects, or what-have-you, but I do know that I am responsible for deleting the array.

When I delete each object in my array, should the destructor for CEntity not be called at all just because one of them is a CWorldObject and in the CWorldObject class the destructor was not declared as virtual?

Or wait. So I delete the object as a CEntity, and CWorldObject’s destructor is NOT virtual. So that means the destructor for CWorldObject won’t be called?

But wait again. Another class inherits from CWorldObject but its destructor is virtual. So now what happens when you delete it as a CEntity??

This was the point of my previous question. How does it possibly make sense and what behavior would you expect?

When I was a kid there was a commercial by Smokey the Bear. How did it go?
Oh yes. “Only ‘once virtual, always virtual’ can prevent forest fires.”

L. Spiro

• ### Game Developer Survey

We are looking for qualified game developers to participate in a 10-minute online survey. Qualified participants will be offered a \$15 incentive for your time and insights. Click here to start!

• 9
• 19
• 36
• 9
• 16