M2103-TP6-Exo-3

La classe Duree a été partiellement étudiée précédemment.

La dernière version qui en a été faite sert de point de départ à cet exercice.

Créer le projet CDureeEditable.

Y incorporer les fichiers  :

IEditable.hpp

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

#include <iostream>

namespace nsUtil
{
    class IEditable;
    std::ostream & operator << (std::ostream & os, const IEditable & obj);
    
    class IEditable
    {
        virtual std::ostream & display (std::ostream & os) const = 0;
      public :
        virtual ~IEditable (void) {}
        friend std::ostream & operator << (std::ostream & os, const IEditable & obj);

    }; // IEditable
    
} // namespace nsUtil

inline std::ostream & nsUtil::operator << (std::ostream & os, const IEditable & obj)
{
    return obj.display (os);
}

#endif /* __IEDITABLE_HPP__ */

Duree.h

 
/**
 *
 * \file    Duree.h
 *
 * \authors M. Laporte
 *
 * \date    02/04/2018
 *
 * \version V2.0
 *
 * \brief  déclarations de la classe Duree (avec constructeurs et 
 *         destructeur)
 *
 **/
 
 #ifndef __DUREE_H__
 #define __DUREE_H__
 
namespace nsUtil
{
    typedef unsigned long long ULLong_t;

	class Duree
	{
	  private :
		ULLong_t       myDuree;
		short unsigned mySeconds;
		short unsigned myMinutes;
		short unsigned myHours;
		ULLong_t       myDays;

		void normaliser (void);

	  public :
		Duree  (const ULLong_t duree = ULLong_t (0));
		Duree  (const Duree & duree);
		~Duree (void);

		ULLong_t getDuree (void) const;

		void display (void) const;

		void incr (const ULLong_t delta = ULLong_t (0));
		void decr (const ULLong_t delta = ULLong_t (0));
		
		Duree operator +  (const Duree & d) const;
		Duree operator -  (const Duree & d) const;
		
		bool  operator >  (const Duree & d) const;
		bool  operator <  (const Duree & d) const;
		bool  operator != (const Duree & d) const;
		bool  operator == (const Duree & d) const;

	}; // Duree

} // nsUtil

#endif /* __DUREE_H__ */

Duree.cpp

 
/**
 *
 * \file    Duree.cpp
 *
 * \authors M. Laporte
 *
 * \date    02/04/2018
 *
 * \version V2.0
 *
 * \brief  définitions de la classe Duree
 *
 **/
#include <iostream>
#include <iomanip>   // setw()
#include "Duree.h"

using namespace nsUtil;
using namespace std;

#define DUREE nsUtil::Duree

DUREE::Duree  (const ULLong_t duree /* = ULLong_t (0) */) 
    : myDuree (duree) 
{ 
	normaliser ();
	cout << "duree construite : ";
	display ();
    cout << endl;	
	
} // Duree()

DUREE::Duree  (const Duree & duree) 
    : myDuree (duree.getDuree ()) 
{ 
	normaliser ();
	cout << "duree construite par recopie : ";
	display ();
    cout << endl;	
	
} // Duree()

DUREE::~Duree  (void) 
{ 
	cout << "duree détruite : ";
	display ();
    cout << endl;	
	
} // Duree()

void DUREE::normaliser (void)
{
	myDays    =  myDuree / 86400;
	myHours   = (myDuree % 86400) / 3600;
	myMinutes  = (myDuree % 3600) / 60;
	mySeconds =  myDuree % 60;
	
} // normaliser()

ULLong_t DUREE::getDuree (void) const { return myDuree; }

void DUREE::display (void) const
{
	cout << '[' 
	     << setw (10) << myDays    << " jour (s) " 
	     << setfill ('0')
		 << setw (2)  << myHours   << " heure(s) "
		 << setw (2)  << myMinutes << " minute(s) "
		 << setw (2)  << mySeconds << " seconde(s) "
		 << setfill (' ')
		 << ']';
		 
} // display()

void DUREE::incr (const ULLong_t delta /* = ULLong_t (0) */)
{
	myDuree += delta;
	normaliser ();
	
} // incr()

void DUREE::decr (const ULLong_t delta /* = ULLong_t (0) */)
{
	myDuree -= (delta > myDuree) ? myDuree : delta;
	
} // decr()

DUREE DUREE::operator + (const Duree & d) const
{
	return myDuree + d.myDuree;
	
} // operator +()

DUREE DUREE::operator - (const Duree & d) const
{
	return myDuree - (myDuree < d.myDuree ? myDuree : d.myDuree);
	
} // operator -()

bool DUREE::operator > (const Duree & d) const
{
	return myDuree > d.myDuree;
	
} // operator >()

bool DUREE::operator < (const Duree & d) const
{
	return myDuree < d.myDuree;
	
} // operator <()

bool DUREE::operator != (const Duree & d) const
{
	return myDuree != d.myDuree;
	
} // operator !=()

bool DUREE::operator == (const Duree & d) const
{
	return myDuree == d.myDuree;
	
} // operator ==()

#undef DUREE

De nombreuses améliorations vont lui être apportées.

Copiez aussi le programme de test

testDuree.cpp


/**
 *
 * @file    TestDuree.cpp
 *
 * @authors M. Laporte, D. Mathieu
 *
 * @date    17/03/2010
 *
 * @version V1.0
 *
 * @brief   Test de la classe CDuree complete
 *
 **/
#include <cassert>
#include <sstream>
#include <exception>
#include <iostream>

#include "CException.h"    // de l'exercice précédent
#include "CstCodErr.h"
#include "Duree.h"

using namespace std;
using namespace rel_ops;
using namespace nsUtil;    // CException

namespace
{
    void testDuree_01 (void)
    {
        DureeEditable d1 (3661);
        DureeEditable d2 (2661);
        DureeEditable d3 (3661);

        assert (! (d1 < d2));
        assert (  (d2 < d1));

        assert (   d1 > d2);
        assert (! (d2 > d1));

        assert (! (d1 <= d2));
        assert (   d2 <= d1);

        assert (   d1 >= d2);
        assert (! (d2 >= d1));

        assert (! (d1 == d2));
        assert (! (d2 == d1));
        assert (   d1 == d3);

        assert (   d1 != d2);
        assert (   d2 != d1);

    } // testDuree_01()

    void testDuree_02 (void)
    {
        DureeEditable d1 (3661);
        {
            ostringstream oss;
            oss << d1;
            assert (oss.str() == "[     0:01:01:01]");
        }
        {
            ostringstream oss;
            oss << d1--;
            assert (oss.str() == "[     0:01:01:01]");
        }
        {
            ostringstream oss;
            oss << d1--;
            assert (oss.str() == "[     0:01:01:00]");
        }
        {
            ostringstream oss;
            oss << --d1;
            assert (oss.str() == "[     0:01:00:58]");
        }
        {
            ostringstream oss;
            oss << d1;
            assert (oss.str() == "[     0:01:00:58]");
        }
        {
            ostringstream oss;
            oss << d1++;
            assert (oss.str() == "[     0:01:00:58]");
        }
        {
            ostringstream oss;
            oss << d1++;
            assert (oss.str() == "[     0:01:00:59]");
        }
        {
            ostringstream oss;
            oss << ++d1;
            assert (oss.str() == "[     0:01:01:01]");
        }
        {
            ostringstream oss;
            oss << ++d1;
            assert (oss.str() == "[     0:01:01:02]");
        }
        {
            ostringstream oss;
            oss << ++d1;
            assert (oss.str() == "[     0:01:01:03]");
        }
        {
            ostringstream oss;
            oss << (d1 -= 3);
            assert (oss.str() == "[     0:01:01:00]");
        }
        {
            ostringstream oss;
            oss << (d1 += 3);
            assert (oss.str() == "[     0:01:01:03]");
        }
        {
            ostringstream oss;
            oss << (d1 += Duree (3));
            assert (oss.str() == "[     0:01:01:06]");
        }
        {
            d1.setDuree (0);
            ostringstream oss;
            oss << d1;
            assert (oss.str() == "[     0:00:00:00]");
        }

    } // testDuree_02)

    void testDuree_03 (void)
    {
        DureeEditable d1;
        bool isCaught = false;

        try { d1--; }
        catch (const CException & e) { isCaught = true; }
        assert (isCaught);

        isCaught = false;
        try { --d1; }
        catch (const CException & e) { isCaught = true; }
        assert (isCaught);

        isCaught = false;
        try { d1 -= 1; }
        catch (const CException & e) { isCaught = true; }
        assert (isCaught);

        isCaught = false;
        try { d1 -= Duree (3); }
        catch (const CException & e) { isCaught = true; }
        assert (isCaught);

    } // testDuree_03()

} // namespace anonyme

int main (int argc, char * argv [])
{
    if (argc != 1)
    {
        cerr << "Nombre d'arguments invalide\n"
                "Usage : TestCDuree\n";
        return KErrArg;
    }
    try
    {
        testDuree_01 ();
        testDuree_02 ();
        testDuree_03 ();
        cout << "Fin normale\n";

        return KNoExc;
    }
    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;
    }

} // main()

Modifications à effectuer dans la classe Duree :

  • ajouter le qualifieur explicit devant le constructeur par défaut (cela évite les conversions implicites
    de n’importe quel entier en Duree, que pourrait faire indûment le compilateur),
  • remplacer les fonctions incr() et decr() par les opérateurs de pre/post-in/dé crémentation,
    CX & operator ++ (void) noexcept; // préincrémentation de la classe CX
    CX   operator ++ (int)  noexcept; // postincrémentation de la classe CX
    
    
  • ajouter les deux surcharges de chacun des opérateurs d’affectation += et -= ayant pour paramètre soit un entier unsigned long long, soit un objet Duree (profile),
    Duree & operator += (const Duree &) noexcept;
    
  • ajouter les deux opérateurs + et - ayant pour paramètre un entier
    unsigned long long,
  • ajouter le modifieur setDuree() ayant pour paramètre un unsigned long long avec une valeur
    par défaut,
  • les opérateurs -, -- et -= sont susceptibles de lever une
    CException de code d’erreur KExcOpInterdite de valeur 201.

Un objet ne doit pas savoir comment il doit être affiché (nous avons fait une exception pour la classe
CException qui a pour vocation d’être affiché sur un flux standard de sortie).
La fonction display() n’a donc rien à faire dans la classe Duree.

Dans l’espace de nom anonyme du fichier TestDuree.cpp écrire la classe DureeEditable.

    • La dériver publiquement des classes Duree et IEditable (penser à inclure les
      fichiers IEditable.hpp et Duree.h).
    • Supprimer la fonction-membre publique display() de la classe Duree et ajouter la fonction-membre protégée display(), de même profil que la fonction abstraite display() de IEditable à la classe DureeEditable.

Modifier la fonction main() du fichier TestDuree.cpp, pour lui conserver la structure qui a été utilisée dans l’exercice précédent.

Compiler et tester.