web-dev-qa-db-fra.com

Création d'exceptions personnalisées en C++

J'apprends le C++ et j'essaye de créer ma propre exception et de la lancer sous Linux. 

J'ai créé un petit projet de test pour tester mon implémentation et voici mon fichier d'en-tête de classe d'exception.

class TestClass : public std::runtime_error
{
public:
    TestClass(char const* const message) throw();
    virtual char const* what() const throw();
};

Le fichier source de la classe d'exception est

using namespace std;

TestClass::TestClass(char const* const message) throw()
    : std::runtime_error(message)
{

}

char const * TestClass::what() const throw()
{
    return exception::what();
}

Dans mon application principale, j'appelle une fonction qui lève mon exception et l'attrape dans un try/catch comme suit:

void runAFunctionAndthrow();

/*
 * 
 */
int main(int argc, char** argv) {
    try
    {
        cout << "About to call function" << endl;
        runAFunctionAndthrow();
    }
    catch (TestClass ex)
    {
        cout << "Exception Caught: " << ex.what() << endl;
    }

    return 0;
}

void runAFunctionAndthrow()
{
    cout << "going to run now. oh dear I need to throw an exception" << endl;

    stringstream logstream;
    logstream << "This is my exception error. :(";
    throw TestClass(logstream.str().c_str());
}

Quand je cours, je m'attends à obtenir le résultat suivant:

Sur le point d'appeler la fonction 

Va courir maintenant. oh mon dieu j'ai besoin de lancer une exception

Exception Caught: Ceci est mon erreur d'exception. :(

Au lieu de cela, je reçois

Sur le point d'appeler la fonction

va courir maintenant. oh mon dieu j'ai besoin de lancer une exception

Exception Caught: std :: exception

Notez que la dernière ligne indique std :: exception au lieu de mon message d’exception "Ceci est mon erreur d’exception". 

Pourquoi cela fonctionne-t-il correctement sous Windows mais sous Linux? 

D'après ce que j'ai vu sur différents articles, ce que j'ai fait est correct, alors qu'est-ce qui me manque? 

18
Boardy

Votre what() renvoie:

 return exception::what();

La valeur de retour de std::exception::what() est spécifiée comme suit :

Pointeur sur une chaîne à zéro terminal contenant des informations explicatives.

C'est tout. Rien de plus, rien d'autre. Le texte que vous affichez constitue certainement une "information explicative". Et c’est la seule condition requise pour la valeur de retour de what() (à l’exception d’une autre qui n’est pas pertinente ici).

En d'autres termes, C++ ne garantit pas le contenu exact de ce que vous obtenez avec what(). what() que vous voyez est what() vous obtenez, comme dit le proverbe.

Si vous voulez que votre exception se décrive elle-même, d'une certaine manière, c'est à vous de l'implémenter, dans le cadre de votre what().

22
Sam Varshavchik

Vous avez besoin de votre propre implémentation de la méthode what () ou utilisez std::runtime_error::what() comme écrit dans les commentaires.

Dire:

class TestClass : public std::runtime_error
{
    std::string what_message;
public:
    const char* what() override
    {
        return what_message.c_str();
    }
};

En outre, il vaut mieux utiliser noexcept au lieu de throw() et seulement après avoir pris connaissance de ces informations - link .

Et dans votre try-catch:

catch (const TestClass& myException)

Au lieu de catch(TestClass myException) - sinon, vous effectuez une copie implicite pouvant éventuellement entraîner une exception. Cela rompt également le polymorphisme: si vous voulez utiliser une instance d'implémentation catchpure virtual interface, vous devrez utiliser une référence.

16
andrgolubev

Vous avez besoin d’un moyen de spécifier un message d’erreur personnalisé à std :: exception qui n’est pas autorisé. Voir ceci pour une solution possible.

0
Furkan Fidan