Chapitre 8 : exceptions — Solutions #
Serie 8.1 #
Exercice 1 : validation avec exceptions #
1242.2_08.01_ExceptionValidation
MyException.h
#pragma once
#include <exception>
#include <string>
class MyException : public std::exception
{
public:
MyException() noexcept = default;
explicit MyException(std::string msg) noexcept;
virtual ~MyException() = default;
const char* what() const noexcept override;
private:
std::string m_errorMessage{"Undefined error!"};
};MyException.cpp
#include "MyException.h"
MyException::MyException(std::string msg) noexcept
: m_errorMessage(std::move(msg))
{
}
const char* MyException::what() const noexcept
{
return m_errorMessage.c_str();
}main.cpp
#include <iostream>
#include <print>
#include "MyException.h"
void isPositive(int value);
void isOdd(int value);
void isLessThan(int value, int maxValue);
void isGreaterThan(int value, int minValue);
int main()
{
auto minValue = 10;
auto maxValue = 100;
try
{
int value;
std::print("Enter a positive and odd value [{}, {}] : ", minValue, maxValue);
std::cin >> value;
isPositive(value);
isOdd(value);
isLessThan(value, maxValue);
isGreaterThan(value, minValue);
std::println("Correct value !");
}
catch (int val)
{
std::println("Incorrect value ! -> {}", val);
}
catch (const char* str)
{
std::println("Incorrect value ! -> {}", str);
}
catch (const MyException& err)
{
std::println("Incorrect value ! -> {}", err.what());
}
catch (...)
{
std::println("Unknown error !");
}
return 0;
}
void isPositive(int value)
{
if (value < 0)
{
throw value;
}
std::println("- OK: It's a positive value");
}
void isOdd(int value)
{
if (value % 2 == 0)
{
throw "The value is even";
}
std::println("- OK: It's an odd value");
}
void isLessThan(int value, int maxValue)
{
if (value > maxValue)
{
throw MyException("The value is too large");
}
std::println("- OK: It's a value less than {}", maxValue);
}
void isGreaterThan(int value, int minValue)
{
if (value < minValue)
{
throw MyException("The value is too small");
}
std::println("- OK: It's a value greater than {}", minValue);
}Serie 8.2 #
Exercice 1 : classe Vector avec exceptions #
📝 À NOTER
Remarque – bonne pratique
Pour des raisons pédagogiques, cette solution attrape std::bad_alloc directement dans les constructeurs et l’operator=.
Ce n’est pas la pratique recommandée.
En production, un constructeur devrait laisser propager l’exception : l’objet ne sera alors jamais considéré comme construit, et c’est à l’appelant de décider quoi faire (abandonner, retenter avec une taille plus petite, logger, etc.).
1242.2_08.02_ExceptionVector
Vector.h
#pragma once
#include <iosfwd>
class Vector
{
public:
Vector() = default;
Vector(int size, int value = 0);
Vector(const Vector& v);
virtual ~Vector();
Vector& operator=(const Vector& v);
friend Vector operator+(const Vector& v1, const Vector& v2);
int& operator[](int i);
long long getSizeInBytes() const
{
return static_cast<long long>(m_size) * sizeof(*m_data);
}
friend std::ostream& operator<<(std::ostream& out, const Vector& v);
private:
int *m_data{nullptr};
int m_size{0};
void cleanup();
};Vector.cpp
#include "Vector.h"
#include <iostream>
#include <print>
#include <new>
#include <stdexcept>
Vector::Vector(int size, int value)
{
try
{
m_size = size;
m_data = new int[m_size];
for (int i = 0; i < m_size; i++)
{
m_data[i] = value;
}
}
catch (const std::bad_alloc &e)
{
std::println(" caught in Vector(int, int) >>> {}", e.what());
cleanup();
}
}
Vector::Vector(const Vector &v)
{
try
{
m_size = v.m_size;
m_data = new int[m_size];
for (int i = 0; i < m_size; i++)
{
m_data[i] = v.m_data[i];
}
}
catch (const std::bad_alloc &e)
{
std::println(" caught in Vector(const Vector&) >>> {}", e.what());
cleanup();
}
}
Vector::~Vector()
{
cleanup();
}
Vector &Vector::operator=(const Vector &vec)
{
if (this != &vec)
{
cleanup();
try
{
m_size = vec.m_size;
m_data = new int[m_size];
for (int i = 0; i < m_size; i++)
{
m_data[i] = vec.m_data[i];
}
}
catch (const std::bad_alloc &e)
{
std::println(" caught in operator= >>> {}", e.what());
cleanup();
}
}
return *this;
}
int &Vector::operator[](int i)
{
if (m_data != nullptr && i >= 0 && i < m_size)
{
return m_data[i];
}
throw std::out_of_range(" thrown from operator[] :: Out of range");
}
void Vector::cleanup()
{
delete[] m_data;
m_data = nullptr;
m_size = 0;
}
std::ostream &operator<<(std::ostream &out, const Vector &v)
{
out << "[ ";
for (int i = 0; i < v.m_size; i++)
{
out << v.m_data[i] << ' ';
}
out << "]";
return out;
}
Vector operator+(const Vector &v1, const Vector &v2)
{
if (v1.m_size == v2.m_size)
{
Vector result(v1.m_size);
for (int i = 0; i < v1.m_size; i++)
{
result.m_data[i] = v1.m_data[i] + v2.m_data[i];
}
return result;
}
return v1;
}main.cpp
#include <print>
#include <vector>
#include <cmath>
#include <limits>
#include "Vector.h"
int main()
{
const int SIZE = INT_MAX;
// A) Allocation test in constructor Vector(int, int)
std::println("Vector v1({});", SIZE);
Vector v1(SIZE);
// B) Allocation test in assignment operator
auto nbOfTry = 10;
std::vector<Vector> tabV(nbOfTry);
for (int i = 0; i < nbOfTry; i++)
{
std::println("Allocation of the {}th vector of {} elements", i + 1, SIZE);
tabV[i] = v1;
}
// C) Size of allocated memory
long long sumInBytes = 0;
for (auto &v : tabV)
{
sumInBytes += v.getSizeInBytes();
}
std::println("Memory allocated : {} Bytes", sumInBytes);
std::println("Memory allocated : {} GB (1000)", sumInBytes / std::pow(1000, 3));
std::println("Memory allocated : {} GB (1024)", sumInBytes / std::pow(1024, 3));
// D) Allocation test in constructor Vector(int, int)
std::println("Vector v2({});", SIZE);
Vector v2(SIZE);
// E) Allocation test in copy constructor Vector(const Vector&)
std::println("Vector v3 = v1;");
Vector v3 = v1;
// F) Allocation test in assignment operator
std::println("Vector v5;");
Vector v5;
std::println("v5 = v1;");
v5 = v1;
// G) Allocation test with wrong value
std::println("Vector v6(-1);");
Vector v6(-1);
// H) Out-of-range access in Vector
try
{
std::println("v1[-1] = 5;");
v1[-1] = 5;
}
catch (const std::out_of_range& e)
{
std::println(" caught in main() >>>> {}", e.what());
}
// I) Out-of-range access in std::vector
try
{
std::println("tabV.at(-1).getSizeInBytes()");
std::println("{}", tabV.at(-1).getSizeInBytes());
}
catch (const std::exception& e)
{
std::println(" caught in main() >>>> {}", e.what());
}
return 0;
}