-
Implémentez dans un fichier 1.1.cc la classe Pixel
déclarée ci-dessous (télécharger: 1.1.h, ne le modifiez pas!):
class Pixel {
public:
Pixel(int x, int y);
int X() const;
int Y() const;
// Prints "INVALID" if the pixel is not valid, otherwise prints "(x, y)".
void DebugPrint() const;
protected:
// A valid pixel is a pixel with non-negative coordinates.
bool IsValid() const;
private:
const int x_;
const int y_;
};
Testez votre code avec:
rm 1.tar.gz; wget --no-cache http://fabien.viger.free.fr/cpp/td9/1.tar.gz && tar xf 1.tar.gz
make 1.1
RENDU: 1.1.cc
-
Copiez 1.1.h et 1.1.cc dans des fichiers
1.2.h et 1.2.cc.
Ajoutez en bas de 1.2.h le code suivant:
class ColoredPixel : public Pixel {
public:
ColoredPixel(int x, int y, int color_rgb);
int ColorRgb() const;
// Like before, but we also print the color like this:
// (4, 3, 0xff0080) -> "(4, 3, R255:G0:B128)"
void DebugPrint() const;
// We inherit Pixel::IsValid() and don't change it. We don't do more checks.
private:
const int color_rgb_;
};
Implémentez cette classe en bas de 1.2.cc
Indications
-
Le terme 0xff0080 utilisée dans mon exemple correspond à
l'écriture hexadécimale,
en base 16, qui est très facile à traduire en binaire:
0x0 = 0000b,
0x1 = 0001b,
0x2 = 0010b,
0x3 = 0011b,
0x4 = 0100b,
0x5 = 0101b,
0x6 = 0110b,
0x7 = 0111b,
0x8 = 1000b,
0x9 = 1001b,
0xA = 1010b,
0xB = 1011b,
0xC = 1100b,
0xD = 1101b,
0xE = 1110b,
0xF = 1111b,
Et du coup: 0x3e5 = 0011 1110 0101 = 001111100101 en binaire.
-
La décomposition RGB d'un entier est un grand classique en imagerie:
Si on regarde les bits d'un entier qui représente une couleur RGB, ses 24 derniers bits sont
rrrrrrrrggggggggbbbbbbbb :
- La composante R (Red) correspond aux bits 16..23
- La composante G (Green) correspond aux bits 8..15
- La composante B (Blue) correspond aux bits 0..7
-
Pour extraire un sous-bloc des bits d'un entier, on peut utiliser les opérations >> et & :
- >>: décalage à droite. x >> 7 == x * 27
- &: le ET bit-à-bit (à différencier du ET booléen && !!): x & 3 == les deux derniers bits de x (car 3 = 11 en binaire).
Par exemple, pour extraire les bits 11..15 d'un entier x on peut faire:
(x >> 11) & 0x1F car 0x1F == 11111 en binaire (== 31 en décimal).
Testez votre code avec:
make 1.2
RENDU: 1.2.cc
-
Regardez le code suivant (télécharger: 1.3.test.cc):
#include "1.2.h"
void ApplyDebugPrintTo(const Pixel* p) {
p->DebugPrint();
}
int main() {
ColoredPixel colored_pix(1, 2, 0x334455);
ApplyDebugPrintTo(&colored_pix);
colored_pix.DebugPrint();
((const Pixel*)(&colored_pix))->DebugPrint();
Pixel p = colored_pix;
p.DebugPrint();
}
Faites-le tourner: make 1.3.test
./1.3.test
Modifiez 1.2.h sans toucher à 1.2.cc pour que les 3 premières lignes soient comme la deuxième.
Vérifiez que le 1.2 marche encore: make 1.2
RENDU: 1.2.h modifié
-
Copiez 1.2.h et 1.2.cc dans 1.4.h et 1.4.cc,
et ré-implémentez la classe ColoredPixel en utilisant la composition:
on aura un membre privé Pixel pixel_; au lieu d'hériter de la classe Pixel
Vérifiez tout seuls, comme des grands:
- En copiant 1.2.test.cc dans 1.4.test.cc
- Et en y changeant rien à part le: #include "1.2.h"
- En copiant 1.2.test.sh dans 1.4.test.sh
- Et en y changeant rien à part la référence à 1.2.test
- Et en n'oubliant pas de le rendre éxécutable (chmod +x 1.4.test.sh)
- Et en ajoutant des entrées pour le 1.4 dans le Makefile.
- La commande suivante doit marcher et faire tourner votre code:
make 1.4
RENDU: 1.4.h, 1.4.cc, 1.4.test.cc, et le Makefile modifié.