Recipe for `final`: omit `virtual`?
Is it a valid recipe to say that if I write final
(to a member function) one shoul开发者_StackOverflow社区d not write virtual
?
In a base class, final
methods would make no sense:
struct Driver {
virtual void print();
};
If one would add final
to print()
this would defy the reason for polymorphism in the first place. So that would be useless (though possible).
When I derive from this class I can detect errors with final
, but only without virtual
:
struct KeyboardDriver : public Driver {
virtual void prynt() final; // Oops: typo, but compiler-ok
};
struct MouseDriver : public Driver {
void prynt() final; // Error: Hooray, compiler found my typo
};
The additional final
for KeyboardDriver::prynt
was legal. Because final
only requires the member function to be virtual
-- the compiler lets this pass (FDIS 9.2p9).
But when I leave out the virtual
the typo makes this function non-virtual -- it overrides nothing, i.e. no virtual function. Therefore final
without virtual
serves the same purpose to this respect as override
does.
Update: Is my analysis correct? Does the functionality of final
without virtual
include that one of override
?
Your analysis is correct. Not marking a final
member as virtual
avoids declaring a new, non-overriden member and catches mistakes. However, since that's the purpose of override
, it may be simpler to just use final override
; then whether the member is marked virtual
or not won't matter at all.
That is not what final
is for. What you are looking for is override
.
struct Base {
virtual void print();
};
struct Derived : Base {
void prynt() override; //compiler error
};
struct Good : Base {
void print() override; //no compiler error
};
If you mark a function as override
when it does not, then you get an error. Combined with your final function, you get all the comforts of compiler checked safety, with the clarity of explicitly marking functions virtual
when coding standards demand it.
struct Best : Base {
virtual void print() final override;
};
I do not think it is an error, it's just a virtual function that can not be overloaded. Same thing that would happen if the function were declared virtual in a parent class, since virtual declarations are inherited. It would make no sense to forbid it.
Is my analysis correct? Does the functionality of final without virtual include that one of override?
No. The reason that this was a compiler error:
void prynt() final; // Error: Hooray, compiler found my typo
Is because final
is only allowed on virtual functions. The compiler is complaining because you used it on a function that isn't virtual.
There is nothing syntactically wrong about this line:
virtual void prynt() final; // Oops: typo, but compiler-ok
It may not be what you want, but this is legitimate (and even meaningful, depending on the circumstances) code.
The problem you are encountering is due to wanting to do this:
struct Driver {
virtual void print();
};
struct MouseDriver : public Driver {
void print();
};
Omitting the virtual
is technically legal. But personally, I've always felt that it was bad form. You're putting vital information (which functions are overridden) into another class. I think it was a mistake to even allow this to compile.
If you want to avoid this problem, then explicitly state virtual
on all virtual functions, and use override
in the places where you mean to create a new function. Then, this will fail to compile correctly.
struct Driver {
virtual void print();
};
struct MouseDriver : public Driver {
virtual void print() override;
};
精彩评论