web-dev-qa-db-fra.com

la spécification d'exception de la fonction de remplacement est plus laxiste que la version de base

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?

7
reavenisadesk

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 que B::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.

5
P.W

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 whatnoexcept 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).

6
Daniel Langr

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
1
JVApen