web-dev-qa-db-fra.com

Bonne façon d'hériter de std :: exception

Je viens de créer une hiérarchie d'exceptions et je voulais passer char* Au constructeur d'une de mes classes dérivées avec un message indiquant ce qui ne va pas, mais apparemment std::exception N'a pas de constructeur qui me permettrait de faites-le. Pourtant, il existe un membre de classe appelé what() qui suggère que certaines informations peuvent être transmises.
Comment puis-je (puis-je?) Passer du texte à la classe dérivée d'un std::exception Afin de passer des informations avec ma classe d'exception, donc je peux dire quelque part dans le code:

throw My_Exception("Something bad happened.");
50
smallB

Si vous souhaitez utiliser le constructeur de chaîne, vous devez hériter de std :: runtime_error ou std :: logic_error qui implémente un constructeur de chaîne et implémente l'exception std :: :: quelle méthode.

Ensuite, il s'agit simplement d'appeler le constructeur runtime_error/logic_error à partir de votre nouvelle classe héritée, ou si vous utilisez c ++ 11, vous pouvez utiliser l'héritage du constructeur.

53
obmarg

J'utilise la classe suivante pour mes exceptions et cela fonctionne très bien:

class Exception: public std::exception
{
public:
    /** Constructor (C strings).
     *  @param message C-style string error message.
     *                 The string contents are copied upon construction.
     *                 Hence, responsibility for deleting the char* lies
     *                 with the caller. 
     */
    explicit Exception(const char* message):
      msg_(message)
      {
      }

    /** Constructor (C++ STL strings).
     *  @param message The error message.
     */
    explicit Exception(const std::string& message):
      msg_(message)
      {}

    /** Destructor.
     * Virtual to allow for subclassing.
     */
    virtual ~Exception() throw (){}

    /** Returns a pointer to the (constant) error description.
     *  @return A pointer to a const char*. The underlying memory
     *          is in posession of the Exception object. Callers must
     *          not attempt to free the memory.
     */
    virtual const char* what() const throw (){
       return msg_.c_str();
    }

protected:
    /** Error message.
     */
    std::string msg_;
};
59
tune2fs

Que dis-tu de ça:

class My_Exception : public std::exception
{
public:
virtual char const * what() const { return "Something bad happend."; }
};

Ou, créez un constructeur acceptant la description si vous le souhaitez ...

7
user472155

Si votre objectif est de créer une exception afin de ne pas lever d'exception générique ( cpp: S112 ) vous pouvez simplement exposer l'exception dont vous héritez ( C++ 11 ) avec une déclaration using.

Voici un exemple minimal pour cela:

#include <exception>
#include <iostream>

struct myException : std::exception
{
    using std::exception::exception;
};

int main(int, char*[])
{
    try
    {
        throw myException{ "Something Happened" };
    }
    catch (myException &e)
    {
        std::cout << e.what() << std::endl;
    }
    return{ 0 };
}

Comme Kilian le souligne dans la section commentaire, l'exemple dépend d'une implémentation spécifique de std :: exception qui offre plus de constructeurs que ceux mentionnés ici .

Pour éviter cela, vous pouvez utiliser l'une des classes de commodité prédéfinies dans l'en-tête <stdexcept>. Voir ces " Catégories d'exceptions " pour l'inspiration.

5
Johannes

La méthode what est virtuelle, ce qui signifie que vous devez la remplacer pour renvoyer le message que vous souhaitez renvoyer.

5