3. Surcharge des opérateurs — Solutions

Chapitre 3 : surcharge des opérateurs — Solutions #

Série 3.1 #

Exercice 1 : classe Time avec surcharge d’opérateurs #

1242.2_03.01_OverloadingTime

Time.h

#include <iosfwd>

class Time
{
public:
    Time();
    explicit Time(int h, int m);
    Time(double realTime); // Implicit conversion intentional: enables expressions like t + 4

    virtual ~Time() = default;

    int getHour() const;
    int getMinute() const;

    void setHour(int h);
    void setMinute(int m);

    Time &operator=(const Time &) = default; // Default memberwise copy is sufficient here

    friend Time operator+(const Time &tm1, const Time &tm2);
    Time operator-(const Time &tm) const;

    bool operator==(const Time &tm) const { return m_hour == tm.m_hour && m_minute == tm.m_minute; }
    bool operator<(const Time &tm) const { return evaluate() < tm.evaluate(); }
    bool operator>=(const Time &tm) const { return !(*this < tm); }
    bool operator<=(const Time &tm) const { return !(tm < *this); }
    bool operator!=(const Time &tm) const { return !(*this == tm); }

    Time &operator++();
    Time operator++(int);

    friend std::istream &operator>>(std::istream &in, Time &tm);
    friend std::ostream &operator<<(std::ostream &out, const Time &tm);

private:
    int m_hour{12};
    int m_minute{0};

    int evaluate() const;

    static constexpr int m_hours_per_day{24};
    static constexpr int m_minutes_per_hour{60};
};

Time.cpp

Time::Time() = default;

Time::Time(int h, int m)
{
    setHour(h);
    setMinute(m);
}

Time::Time(double realTime)
{
    setHour(static_cast<int>(realTime));
    setMinute(static_cast<int>(60.0 * (realTime - static_cast<int>(realTime))));
}

int Time::getHour()   const { return m_hour; }
int Time::getMinute() const { return m_minute; }

void Time::setHour(int h)
{
    m_hour = (h >= 0) ? (h % m_hours_per_day) : 0;
}

void Time::setMinute(int m)
{
    if (m >= 0)
    {
        m_minute = m % m_minutes_per_hour;
        m_hour   = m_hour + m / m_minutes_per_hour;
        setHour(m_hour);
    }
    else
    {
        m_minute = 0;
    }
}

Time Time::operator-(const Time& tm) const
{
    Time result;
    result.setMinute(m_minute - tm.m_minute);
    result.setHour(m_hour - tm.m_hour);
    return result;
}

Time operator+(const Time& tm1, const Time& tm2)
{
    Time result;
    result.setMinute(tm1.m_minute + tm2.m_minute);
    result.setHour(tm1.m_hour + tm2.m_hour);
    return result;
}

int Time::evaluate() const
{
    return m_hour * 60 + m_minute;
}

Time& Time::operator++()
{
    *this = *this + Time(0, 1);
    return *this;
}

Time Time::operator++(int)
{
    Time tmp = *this;
    *this = *this + Time(0, 1);
    return tmp;
}

std::ostream& operator<<(std::ostream& out, const Time& tm)
{
    return out << std::format("{:02d}:{:02d}", tm.m_hour, tm.m_minute);
}

std::istream& operator>>(std::istream& in, Time& tm)
{
    char c;
    int hour, minute;
    in >> hour >> c >> minute;
    if (c == ':')
    {
        tm.setMinute(minute);
        tm.setHour(hour);
        return in;
    }
    in.setstate(std::ios::failbit);
    return in;
}

main.cpp

#include "Time.h"

#include <iostream>

int main()
{
  // Constructors
  std::cout << "Time t1 (default): ";
  Time t1;
  std::cout << t1 << '\n';

  std::cout << "Time t2(10, 9):    ";
  Time t2(10, 9);
  std::cout << t2 << '\n';

  std::cout << "Time t3(17.75):    ";
  Time t3(17.75);
  std::cout << t3 << '\n';

  // Setters
  std::cout << "\nt2.setHour(7):      ";
  t2.setHour(7);
  std::cout << t2 << '\n';

  std::cout << "t2.setMinute(-40):  ";
  t2.setMinute(-40); // negative -> clamped to 0
  std::cout << t2 << '\n';

  std::cout << "t2.setMinute(86):   ";
  t2.setMinute(86); // 86 % 60 = 26 min, +1 hour
  std::cout << t2 << '\n';

  // operator=
  std::cout << "\nt1 = t2:  ";
  t1 = t2;
  std::cout << "t1=" << t1 << "  t2=" << t2 << '\n';

  // operator+ (non-member friend)
  t1.setMinute(0);
  std::cout << "\nt1=" << t1 << "  t3=" << t3 << '\n';
  std::cout << "t1 = t1 + t3: ";
  t1 = t1 + t3;
  std::cout << t1 << '\n';

  std::cout << "t3 = t3 + 4:  ";
  t3 = t3 + 4; // implicit conversion: 4 -> Time(4.0)
  std::cout << t3 << '\n';

  std::cout << "t3 = 4 + t3:  ";
  t3 = 4 + t3;
  std::cout << t3 << '\n';

  // operator- (member)
  std::cout << "\nt1=" << t1 << "  t3=" << t3 << '\n';
  std::cout << "t1 = t1 - t3: ";
  t1 = t1 - t3;
  std::cout << t1 << '\n';

  std::cout << "t3 = t3 - 1:  ";
  t3 = t3 - 1;
  std::cout << t3 << '\n';

  // t3 = 1 - t3 // ???

  // Comparison operators
  std::cout << '\n';
  std::cout << t1 << " == " << t1 << std::boolalpha << " : " << (t1 == t1) << '\n';
  std::cout << t1 << " == " << t2 << std::boolalpha << " : " << (t1 == t2) << '\n';
  std::cout << t1 << " <  " << t1 << std::boolalpha << " : " << (t1 < t1) << '\n';
  std::cout << t1 << " <  " << t2 << std::boolalpha << " : " << (t1 < t2) << '\n';
  std::cout << t1 << " >= " << t1 << std::boolalpha << " : " << (t1 >= t1) << '\n';
  std::cout << t1 << " >= " << t2 << std::boolalpha << " : " << (t1 >= t2) << '\n';
  std::cout << t1 << " != " << t1 << std::boolalpha << " : " << (t1 != t1) << '\n';
  std::cout << t1 << " != " << t2 << std::boolalpha << " : " << (t1 != t2) << '\n';

  // Increment operators
  std::cout << "\nt2=" << t2 << "  t3=" << t3 << '\n';
  std::cout << "t2 = t3++: ";
  t2 = t3++;
  std::cout << "t2=" << t2 << "  t3=" << t3 << '\n';

  std::cout << "t2 = ++t3: ";
  t2 = ++t3;
  std::cout << "t2=" << t2 << "  t3=" << t3 << '\n';

  // operator>>
  std::cout << "\nEnter a time (hh:mm): ";
  std::cin >> t2;
  std::cout << "t2: " << t2 << '\n';

  return 0;
}

Série 3.2 #

Exercice 1 : classe Vector avec surcharge d’opérateurs #

1242.2_03.02_OverloadingVector

Vector.h

#include <iosfwd>

class Vector
{
public:
    Vector() = default;
    explicit Vector(int n, double val = 0);
    Vector(const Vector& v);
    virtual ~Vector();

    Vector& operator=(const Vector& v);
    double& operator[](int i);
    const double& operator[](int i) const;

    friend Vector operator+(const Vector& v1, const Vector& v2);
    friend std::ostream& operator<<(std::ostream& out, const Vector& v);

private:
    double* m_pData{nullptr};
    int  m_size{0};
};

Vector.cpp

Vector::Vector(int n, double val)
    : m_pData(new double[n]), m_size(n)
{
  for (int i = 0; i < m_size; ++i)
  {
    m_pData[i] = val;
  }
}

Vector::Vector(const Vector &v)
    : m_pData(new double[v.m_size]), m_size(v.m_size)
{
  for (int i = 0; i < m_size; ++i)
  {
    m_pData[i] = v.m_pData[i];
  }
}

Vector::~Vector()
{
  delete[] m_pData;
  m_pData = nullptr;
  m_size = 0;
}

Vector &Vector::operator=(const Vector &vec)
{
  if (this != &vec)
  {
    delete[] m_pData;
    m_pData = nullptr;
    m_size = vec.m_size;
    m_pData = new double[m_size];
    for (int i = 0; i < m_size; ++i)
    {
      m_pData[i] = vec.m_pData[i];
    }
  }
  return *this;
}

double &Vector::operator[](int i)
{
  if (i >= 0 && i < m_size)
  {
    return m_pData[i];
  }
  // Out-of-bounds: fall back to first element
  return m_pData[0];
}

const double &Vector::operator[](int i) const
{
  if (i >= 0 && i < m_size)
  {
    return m_pData[i];
  }
  // Out-of-bounds: fall back to first element
  return m_pData[0];
}

std::ostream &operator<<(std::ostream &out, const Vector &v)
{
  out << "[ ";
  for (int i = 0; i < v.m_size; ++i)
  {
    out << v.m_pData[i] << ' ';
  }
  return out << ']';
}

Vector operator+(const Vector &v1, const Vector &v2)
{
  if (v1.m_size != v2.m_size)
  {
    return v1; // sizes differ: return left operand unchanged
  }
  Vector result(v1.m_size);
  for (int i = 0; i < v1.m_size; ++i)
  {
    result.m_pData[i] = v1.m_pData[i] + v2.m_pData[i];
  }
  return result;
}

main.cpp

#include "Vector.h"

#include <iostream>

int main()
{
    Vector v1;
    Vector v2(3);
    Vector v3 = Vector(3, 10);
    std::cout << "v1: " << v1 << "  v2: " << v2 << "  v3: " << v3 << "\n\n";

    // operator=
    std::cout << "v1: " << v1 << "  v3: " << v3 << '\n';
    std::cout << "v1 = v3;\n";
    v1 = v3;
    std::cout << "v1: " << v1 << "  v3: " << v3 << "\n\n";

    // operator[] — write
    std::cout << "v1: " << v1 << '\n';
    std::cout << "v1[2] = 100;\n";
    v1[2] = 100;
    std::cout << "v1: " << v1 << "\n\n";

    // operator[] — read
    std::cout << "v1[2] = " << v1[2] << '\n';
    std::cout << "v3[2] = " << v3[2] << "\n\n";

    // operator[] — out of bounds falls back to v[0]
    std::cout << "v1: " << v1 << '\n';
    std::cout << "v1[1000] = 200;\n";
    v1[1000] = 200;
    std::cout << "v1: " << v1 << "\n\n";

    // operator+ (non-member friend)
    Vector v4(5, 5);
    std::cout << "v1: " << v1 << "  v3: " << v3 << "  v4: " << v4 << '\n';
    std::cout << "v1 = v3 + v4;\n";
    v1 = v3 + v4;
    std::cout << "v1: " << v1 << "  v3: " << v3 << "  v4: " << v4 << "\n\n";

    std::cout << "v1: " << v1 << "  v2: " << v2 << "  v3: " << v3 << '\n';
    std::cout << "v1 = v3 + v3;\n";
    v1 = v3 + v3;
    std::cout << "v1: " << v1 << "  v2: " << v2 << "  v3: " << v3 << '\n';

    return 0;
}