M2103-TP6-Exo-2

Pour être éditée, la classe CException ne dispose actuellement que de la fonction display(), malcommode.

Il serait préférable de surcharger l’opérateur <<, mais si la classe CException doit ultérieurement être dérivée pour être spécialisée (et elle le sera !), le polymorphisme de l’édition ne fonctionnera pas pour cette nouvelle classe.

C’est pourquoi nous allons en faire une classe utilitaire éditable (c’est-à-dire la faire dériver de
la classe IEditable).

Travail demandé

Créer le projet ClasseEditable.

Y copier le contenu des fichiers 

CException.h


/**
 *
 * \file     CException.h
 *
 * \authors  M. Laporte, D. Mathieu
 *
 * \date     10/02/2011
 *
 * \version  V1.0
 *
 * \brief    Declaration de la classe CException
 *
 **/
#ifndef __CEXCEPTION_H__
#define __CEXCEPTION_H__

#include <string>
#include <exception>

#include "CstCodErr.h"

namespace nsUtil
{
    class CException : public std::exception
    {
        std::string myLibelle;
        unsigned    myCodErr;

      public :
        CException (const std::string & libelle = std::string(), 
                    const unsigned      codErr  = KNoExc)     noexcept;
        virtual ~CException (void)                            noexcept;

        const std::string & getLibelle (void) const           noexcept;
        unsigned            getCodErr  (void) const           noexcept;

        virtual const char* what       (void) const           noexcept;

        void display (void) const;

    }; // CException
    
} // namespace nsUtil

#endif /*  __CEXCEPTION_H__  */

CException.cpp


/**
 *
 * \file     CException.cpp
 *
 * \authors  M. Laporte, D. Mathieu
 *
 * \date     10/02/2011
 *
 * \version  V1.0
 *
 * \brief    classe CException
 *
 **/
#include <string>
#include <iostream>

#include "CstCodErr.h"
#include "CException.h"

using namespace std;

#define CEXC nsUtil::CException

//==========================
// Classe nsUtil::CException
//==========================

CEXC::CException (const string & libelle /* = string () */,
                  const unsigned codErr  /* = KNoExc  */) noexcept 
    : myLibelle (libelle), myCodErr (codErr) {}

const string & CEXC::getLibelle (void) const noexcept 
{
    return myLibelle;

} // GetLibelle()

unsigned CEXC::getCodErr (void) const noexcept { return myCodErr;  }

CEXC::~CException (void) noexcept {}

const char* CEXC::what (void) const noexcept  { return myLibelle.c_str(); }

void CEXC::display (void) const
{ 
    cout << "Exception : " << myLibelle << '\n'
         << "Code      : " << myCodErr  << endl;

} // Afficher()

#undef CEXC

et

CstCodErr.h


/**
 *
 * \file     CstCodErr.h
 *
 * \authors  M. Laporte, D. Mathieu
 *
 * \date     10/02/2011
 *
 * \version  V1.0
 *
 * \brief    Codes d'erreurs
 *
 **/
#ifndef __CSTCODERR_H__
#define __CSTCODERR_H__

namespace nsUtil
{
    enum {KNoExc       = 0,
          KNoError     = 0,

          KExcStd      = 254,
          KExcInconnue = 255 
         };

} // namespace nsUtil

#endif /*  __CSTCODERR_H__  */

Les modifications à apporter à la classe CException sont les suivantes :

  • la dériver publiquement de la classe IEditable (penser à inclure le fichier IEditable.hpp)
  • modifier la méthode publique display() pour qu’elle satisfasse aux nécessités de IEditable.

Le programme ci-dessous est seulement destiné à vérifier que les différents
fichiers ci-dessus sont justes, et que le polymorphisme est correctement implémenté pour
les classes IEditable et CException.

Dans l’espace de noms anonyme du fichier testCException.cpp, dériver la classe
CExcFille de CException, lui ajouter directement dans la déclaration :

  • la fonction display(), qui complète l’édition de sa classe
    mère par un message spécifique (n’importe quoi) ;
  • un constructeur permettant de construire l’objet de la classe mère (passage d’un libellé et d’une constante entière).

Dans la fonction testCException(), lever une exception de la classe CExcFille.

Dans la fonction main(), rétablir le traitement classique des exceptions, en utilisant le nouveau comportement éditable de la classe CException :

int main ()
{
    try 
    { 
        testCException(); 
    }
    catch (const CException & e)
    {
        cerr << e << '\n';
        return e.getCodErr ();
    }
    catch (const exception & e)
    {
        cerr << "Exception standard : " << e.what() << '\n';
        return KExcStd;
    }
    catch (...)
    {
        cerr << "Exception inconnue\n";
        return KExcInconnue;
    }
    return KNoExc;

} // main()

Lui ajouter la vérification que la commande n’a aucun argument, comme dans l’exercice
“Classe abstraite IEditable
Compiler et tester.

Vérifier que la fonction main() affiche bien l’exception levée.

La classe CException est elle aussi devenue un utilitaire.

Pour simplifier les éditions de liens ultérieures, nous vous recommandons de plus d’effectuer les
traitements suivants :

  1. compiler le fichier CException.cpp, par :
    g++ -c CException.cpp -I rep
    

    rep est le répertoire ou se trouve CException.h.

    Noter l’option -I du compilateur g++ qui permet de lui indiquer un chemin où trouver les fichiers de l’utilisateur à inclure s’ils ne sont pas dans le répertoire courant.

  2. ajouter le fichier objet ainsi obtenu dans la bibliothèque libUtil.a :
    ar -cqs libUtil.a CException.o
    

    Vérifier par :

    ar -t libUtil.a
    

Lorsque vous aurez besoin d’utiliser les exceptions (toujours à partir de maintenant) il faudra modifier votre .pro en lui ajoutant la ligne :

LIBS += -L rep -lUtil

rep est le répertoire où se trouve le fichier libUtil.a.