On Wed, 05 Jun 2013 21:14:08 -0400, Jonathan M Davis <[email protected]> wrote:

On Wednesday, June 05, 2013 17:49:17 Walter Bright wrote:
I think we accomplish this in a simpler way:

1. 'virtual' means a method is an "introducing" one.
2. 'override' means a method overrides a base virtual function with a final
function.
3. 'override virtual' means override with a non-final function.
4. none means final and non-overriding.

I would have expected something more like

1. 'virtual' means a method is an "introducing" one.
2. 'override' means override with a non-final function.
3. 'final override' means a method overrides a base virtual function with a
final function.
4. 'final' by itself both mean final and non-overriding.

I agree, I think it can be expressed by answering two questions:

1. Do you want to participate in a base class' virtual call
2. Do you want to allow derived classes to participate in the virtual call.

If you answer yes to 1, add override, otherwise (or if there is no base method), add nothing (in C# answering no, you should add 'new' if there is an existing base function)
If you answer yes to 2, add virtual, otherwise, add final.

But there are a couple of defaults I think are important to establish:
- With no specific storage classes, the default is non-overriding, final.
- When override is specified, the default for allowing participation up the chain switches to virtual. So explicitly stating virtual is OK but redundant. This is where Walter's idea differs. And I think it makes sense, when a base class has a virtual call, the overwhelming default is to continue the virtual chain.

So when answering the original questions [optional]:

1 = yes, 2 = yes, use override [virtual]
1 = no*, 2 = yes, use virtual
1 = yes 2 = no, use override final
1 = no*, 2 = no, use [final]

* note: if no base class virtual function exists, then the answer to question 1 is always no, and override is an error.

The one deviation from the current "require override" behavior of the compiler exposes the following sequence:

1. Base class does not define foo, derived class defines foo, virtual or not.
2. Base class adds foo as virtual

Currently, this will cause an error in the compiler. With this new scheme, the compiler silently accepts this as two unrelated functions, because override is not used. Arguably this is the correct choice, it is what the author of derived originally intended, and C# implies this by compiling, but it does give a warning.

Since we would have no keyword to indicate "non-overriding", a warning is not possible, since there's no explicit way to say "I'm not overriding". I would argue that putting 'new' there doesn't add much, you are unlikely to change your method's semantics to match that of the base class' new method. What the C# explanation I quoted seems to miss is that it's not the author of the derived class who is affected, it's the USER of the derived class. The confusion is for usage, not semantics, and that can be a problem.

Admittedly, the case above should be rather rare. Perhaps the compiler can have a switch which identifies all the places where functions are masked? I would like to see the switch be configurable as to which packages to do this for.

-Steve

Reply via email to