Final ne peut pas être appliqué aux fonctions non virtuelles.
error: seules les fonctions membres virtuelles peuvent être marquées comme 'final'
Il ne serait pas très significatif de pouvoir marquer une méthode non virtuelle comme 'final'. Étant donné
struct A { void foo(); };
struct B : public A { void foo(); };
A * a = new B;
a -> foo(); // cela appellera de toute façon A :: foo, indépendamment de l'existence d'un B::foo
a->foo()
appellera toujours A::foo
.
Mais, si A::foo était virtual
, alors B::foo le remplacerait. Cela pourrait être indésirable, il serait donc logique de rendre la fonction virtuelle finale.
La question est cependant, pourquoi autoriser final sur les fonctions virtuelles. Si vous avez une hiérarchie profonde:
struct A { virtual void foo(); };
struct B : public A { virtual void foo(); };
struct C : public B { virtual void foo() final; };
struct D : public C { /* ne peut pas remplacer foo */ };
Alors le final
met un 'plafond' sur le niveau de substitution possible. D'autres classes peuvent étendre A et B et remplacer leur foo
, mais si une classe étend C, alors cela n'est pas autorisé.
Il ne semble donc probablement pas logique de rendre la fonction 'de niveau supérieur' final, mais cela pourrait avoir du sens plus bas dans la hiérarchie.
(Je pense cependant qu'il y a de la place pour étendre les mots final et override aux membres non virtuels. Ils auraient cepend differente signification.)
31 votes
"n'est-il pas suffisant de déclarer comme non virtuelles vos fonctions « final » Non, les fonctions de remplacement sont implicitement virtuelles que vous utilisiez le mot-clé
virtuel
ou non.15 votes
@ildjarn ce n'est pas vrai si elles n'ont pas été déclarées comme virtuelles dans la super classe, vous ne pouvez pas dériver d'une classe et transformer une méthode non virtuelle en une méthode virtuelle.
10 votes
@DanO je pense que vous ne pouvez pas remplacer mais vous pouvez "cacher" une méthode de cette façon.. ce qui mène à de nombreux problèmes car les gens ne veulent pas cacher les méthodes.
0 votes
@ildjarn Je pense que vous vouliez dire que vous n'avez pas besoin de spécifier le mot-clé 'virtual' dans la classe terminale.. sinon vous avez tort.
16 votes
@DanO: Si ce n'est pas virtuel dans la super classe, alors ce ne serait pas "surcharge".
0 votes
@ildjarn a supprimé l'ancien.
final
usage, empêche le remplacement de la fonction par les classes dérivées. Supposez, j'ai une fonctionvoid func(int);
dans la classe de base. Sifinal
empêche le remplacement, la classe dérivée peut-elle utiliser une liste d'arguments différente pourfunc
? par exemple.void func(int, int) final;
dans la classe dérivée? Mais cela ne fonctionne pas. Le compilateur montre une erreur que vous ne pouvez pas modifier la liste d'arguments.2 votes
Encore une fois, "overriding" a ici un sens spécifique, qui est de donner un comportement polymorphe à une fonction virtuelle. Dans votre exemple,
func
n'est pas virtuelle, il n'y a donc rien à remplacer et donc rien à marquer commeoverride
oufinal
.2 votes
Pour être tatillon, "final" n'est pas un "mot clé" en C++11. C'est en réalité un "identificateur" avec un sens spécial lorsqu'il apparaît dans un certain contexte.
auto final = 10; std::cout << final;
est parfaitement valide, bien que très mal écrit.