Je veux personnaliser une classe d'exception, voici le code:
class TestException : std::exception{
public:
const char *what() const override {
return "TestException";
}
};
J'ai utilisé Clion et le IDE m'a averti de la fonction what()
: exception specification of overriding function is more lax than base version
Mais si je construis le code avec gcc, aucun avertissement n'est sorti ..__ J'ai utilisé c ++ 14, gcc 6.5.0
Quelqu'un peut-il aider à expliquer la signification de l'avertissement et puis-je simplement l'ignorer?
what
from std::exception
est une fonction virtual
et une fonction virtual
dans une classe dérivée ne peut pas avoir de laxer spécification d'exception autre que la fonction qu'elle remplace dans la classe de base.
Ceci est mentionné dans la section "Spéci fi cations d'exception" de la norme.
18.4 Spéci fi cations d'exception [sauf.spec]
...
4. Si une fonction virtuelle a une spéci fi cation d'exception non générée, toutes les déclarations, y compris la définition, de toute fonction qui écrase cette fonction virtuelle dans une classe dérivée doivent avoir une spéci fi cation d'exception non générées, sauf si la fonction dominante est définie comme supprimée .
Et l'exemple donné (qui est un peu similaire au code de la question) l'illustre également.
struct B
{
virtual void f() noexcept;
virtual void g();
virtual void h() noexcept = delete;
};
struct D: B
{
void f(); // ill-formed
void g() noexcept; // OK
void h() = delete; // OK
};
La déclaration de
D::f
est mal formée, car elle comporte une spécification d'exception potentiellement générée, alors queB::f
possède une spécification d'exception non génératrice.
La solution consiste à changer votre code comme suit:
class TestException : std::exception{
public:
const char *what() const noexcept override {
return "TestException";
}
};
Voir compilation ici.
what
La fonction membre de std::exception
est déclarée en tant que noexcept
depuis C++ 11. Par conséquent, vous devez également modifier votre what
noexcept
surchargée. (En fait, c'est ce que dit le message d'erreur.)
Notez que le mot clé noexcept
doit précéder le mot clé override
(voir, par exemple, l'ordre de substitution et noexcept dans standard pour plus de détails).
L'avertissement auquel vous faites face est lié au fait que vous utilisez C++ 14. Si vous compilez avec C++ 17, cela devient une erreur. Par conséquent, je ne recommanderais pas de l'ignorer.
Que se passe-t-il?
std::exception
définit la méthode what
comme suit: virtual const char* what() const noexcept;
. Vous héritez de cette méthode et vous la réimplémentez sans spécifier noexcept
. Par conséquent, vous indiquez que votre implémentation peut générer des exceptions, alors que la méthode de base indique que cela ne devrait jamais être généré. (Et les appelants le supposeront)
Cela a été corrigé dans C++ 17, ce qui a fait noexcept
une partie du système de types et vous oblige à corriger ce code:
const char *what() const noexcept override