You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
218 lines
7.4 KiB
218 lines
7.4 KiB
|
|
|
|
Réponses aux questions posées
|
|
|
|
|
|
|
|
1.2 - Effectivement, et heureusement, selon toute attente, le compilateur
|
|
détecte un eerreur et refuse la compilation lorsque l'on essaie d'atteindre
|
|
un champ privé à partir d'une fonction non membre:
|
|
|
|
complex.h: Dans function « Complex minus(const Complex&, const Complex&) »:
|
|
complex.h:115: error: `double Complex::_re' is private
|
|
|
|
|
|
1.4 - Il est difficile d'ajouter un Constructeur prenant pour argument le
|
|
module et l'argument, ce constructeur aurait la meme "signature" que celui
|
|
prenant comme argument la partie reelle et la partie imaginaire. En effet
|
|
ces quatres parametres seraient vraisemblablement des doubles, et lors de la
|
|
compilation, le compilateur ne pourrait determiner, a l'aide du type des
|
|
arguments, quel constructeur était souhaité.
|
|
|
|
|
|
|
|
|
|
3.1 - Nous avons cree une methode normalize dont le prototype est le suivant :
|
|
|
|
Complex normalize(Complex cpx);
|
|
|
|
Comme le parametre cpx est passe par valeur, il est necessaire d'en effectuer
|
|
une copie sur la pile d'ou l'appel au constructeur de recopie avant l'appel à
|
|
la fonction. On peut noter que la copie est detruite lorsque la fonction se
|
|
termine.
|
|
|
|
Ainsi pour le code suivant :
|
|
|
|
Complex c;
|
|
|
|
[...]
|
|
|
|
std::cout << "Normalisation" << std::endl;
|
|
c = normalize(a);
|
|
std::cout << std::endl;
|
|
std::cout << "Fin de la normalisation" << std::endl;
|
|
|
|
On obtient la trace suivante :
|
|
|
|
(1) +++Complex[0xbfd23db0](0, 0)
|
|
(2) Normalisation
|
|
(3) rrrComplex[0xbfd23d90](1 + i * 1)
|
|
(4) La normalisation a commence
|
|
(5) +++Complex[0xbfd23da0](0.707107, 0.707107)
|
|
(6) ===Complex[0xbfd23da0](0.707107 + i * 0.707107) >> [0xbfd23db0](0 + i * 0)
|
|
(7) ---Complex[0xbfd23da0](0.707107 + i * 0.707107)
|
|
(8) ---Complex[0xbfd23d90](1 + i * 1)
|
|
(9) Fin de la normalisation
|
|
(10) ---Complex[0xbfd23db0](0.707107 + i * 0.707107)
|
|
|
|
Etude de la trace d'execution :
|
|
1 - Declaration du complexe "c", et appel du constructeur par defaut.
|
|
2 - Avant appel a la fonction de normalisation.
|
|
3 - Appel du constructeur de recopie pour passer le complexe sur la pile.
|
|
4 - Dans la fonction de normalisation
|
|
5 - Creation d'un nouveau complexe local
|
|
6 - Affectation de la valeur de retour (complexe local)
|
|
dans la variable c (appartenant à l'appelant)
|
|
7 - Destruction du complexe local
|
|
8 - Destruction du complexe parametre
|
|
9 - Fonction de normalisation terminee
|
|
10 - Destruction du complexe "c"
|
|
|
|
=> Remarque :
|
|
|
|
On remarque qu'un appel au constructeur de recopie est effectue pour passer
|
|
le parametre sur la pile (initialisation d'une zone mémoire "brute"), mais
|
|
que c'est l'opérateur d'affectation qui est utilisé pour recopier la valeur
|
|
de retour (écrasement d'une zone mémoire déjà initialisée)
|
|
|
|
|
|
|
|
|
|
3.2 - Nous avons ajoute une methode dont le prototype est le suivant :
|
|
|
|
Complex Complex::rotate(Complex & c, double angle) const;
|
|
|
|
Ainsi, pour le code suivant :
|
|
|
|
std::cout << "Rotation" << std::endl;
|
|
c = b.rotate(a, M_PI / 2);
|
|
c.writeTo(std::cout);
|
|
std::cout << std::endl;
|
|
std::cout << "Fin de la rotation" << std::endl;
|
|
|
|
et la methode suivante :
|
|
|
|
Complex Complex::rotate(Complex & c, double angle) const {
|
|
Complex tmp = (*this) - c;
|
|
Complex tmp2 = tmp * Complex(cos(angle), sin(angle));
|
|
return tmp2 + c;
|
|
}
|
|
|
|
On obtient la trace d'execution suivante :
|
|
|
|
(1) +++Complex[0xbfd5ef00](0, 0)
|
|
(2) Rotation
|
|
(3) +++Complex[0xbfd5ee80](2, 3)
|
|
(4) +++Complex[0xbfd5ee60](6.12303e-17, 1)
|
|
(5) +++Complex[0xbfd5ee70](-3, 2)
|
|
(6) ---Complex[0xbfd5ee60](6.12303e-17 + i * 1)
|
|
(7) +++Complex[0xbfd5eee0](-2, 3)
|
|
(8) ---Complex[0xbfd5ee70](-3 + i * 2)
|
|
(9) ---Complex[0xbfd5ee80](2 + i * 3)
|
|
(10) ===Complex[0xbfd5eee0](-2 + i * 3) >> [0xbfd5ef00](0.707107 + i * 0.707107)
|
|
(11) ---Complex[0xbfd5eee0](-2 + i * 3)
|
|
(12) Fin de la rotation
|
|
(13) ---Complex[0xbfd5ef00](-2 + i * 3)
|
|
|
|
Etude de la trace d'execution :
|
|
1 - Declaration du complexe "c", et appel du constructeur par defaut.
|
|
2 - Avant appel a la methode de rotation.
|
|
3 - Creation et initialisation de l'objet tmp
|
|
4 - Creation et initialisation du complexe Complex(cos(angle), sin(angle))
|
|
5 - Creation et initialisation de tmp2
|
|
6 - Destruction de Complex(cos(angle), sin(angle))
|
|
7 - Creation et initialisation de tmp2 + c
|
|
8 - Destruction de tmp2
|
|
9 - Destruction de tmp
|
|
10 - Recopie de la valeur de retour (tmp2 + c) dans "c"
|
|
11 - Destruction de la valeur de retour
|
|
12 - Apres appel a la methode de rotation.
|
|
13 - Destruction de "c"
|
|
|
|
=> Remarque :
|
|
On remarque que lors d'un passage d'arguments par référence, le
|
|
constructeur par recopie n'est pas appellé, d'ou un gain de performance.
|
|
Il ne faut cependant pas oublier que l'objet passé par référence est
|
|
modifiable pas la méthode appellée, c'est pourquoi l'utilisation du mot
|
|
clé "const", lorsque cela est possible, est recommandée.
|
|
|
|
|
|
|
|
|
|
3.3 - Nous avons defini une fonction dont le prototype est le suivant :
|
|
|
|
Complex & getMax(Complex & c1, Complex & c2)
|
|
|
|
et nous avons obtenu les resultats suivants :
|
|
|
|
Debut de 'Complex d = getMax(a, b)'
|
|
(1) rrrComplex[0xbfed1af0](3 + i * 4)
|
|
Fin de 'Complex d = getMax(a, b)'
|
|
|
|
Debut de 'c = getMax(a, b)'
|
|
(2) ===Complex[0xbfed1b20](3 + i * 4) >> [0xbfed1b10](-2 + i * 3)
|
|
Fin de 'c = getMax(a, b)'
|
|
|
|
On remarque que :
|
|
1 - Lors d'une initialisation à partir du résultat de la fonction,
|
|
c'est le constructeur par recopie qui est utilisé.
|
|
2 - Lors d'une affectation, c'est la méthode qui surcharge l'opérateur
|
|
d'affectation qui est appellée.
|
|
|
|
|
|
|
|
3.4 - Comme l'énoncé n'est pas très clair, nous avons choisi de remplir le
|
|
tableau selon la méthode suivante :
|
|
|
|
tab[i] = Complex(i, 0);
|
|
|
|
On obtient la trace d'exécution suivante :
|
|
|
|
Debut de l'initialisation du tableau (taille 10)
|
|
(1) +++Complex[0xbf80c330](0, 0)
|
|
+++Complex[0xbf80c340](0, 0)
|
|
+++Complex[0xbf80c350](0, 0)
|
|
+++Complex[0xbf80c360](0, 0)
|
|
+++Complex[0xbf80c370](0, 0)
|
|
+++Complex[0xbf80c380](0, 0)
|
|
+++Complex[0xbf80c390](0, 0)
|
|
+++Complex[0xbf80c3a0](0, 0)
|
|
+++Complex[0xbf80c3b0](0, 0)
|
|
(10) +++Complex[0xbf80c3c0](0, 0)
|
|
Fin de l'initialisation du tableau
|
|
|
|
Appel de la fonction remplirTableau(3, tab)
|
|
(11) +++Complex[0xbf80c2b0](0, 0)
|
|
(12) ===Complex[0xbf80c2b0](0 + i * 0) >> [0xbf80c330](0 + i * 0)
|
|
(13) ---Complex[0xbf80c2b0](0 + i * 0)
|
|
+++Complex[0xbf80c2b0](1, 0)
|
|
===Complex[0xbf80c2b0](1 + i * 0) >> [0xbf80c340](0 + i * 0)
|
|
---Complex[0xbf80c2b0](1 + i * 0)
|
|
+++Complex[0xbf80c2b0](2, 0)
|
|
===Complex[0xbf80c2b0](2 + i * 0) >> [0xbf80c350](0 + i * 0)
|
|
---Complex[0xbf80c2b0](2 + i * 0)
|
|
Fin de l'appel
|
|
|
|
(14) ---Complex[0xbf80c3c0](0 + i * 0)
|
|
---Complex[0xbf80c3b0](0 + i * 0)
|
|
---Complex[0xbf80c3a0](0 + i * 0)
|
|
---Complex[0xbf80c390](0 + i * 0)
|
|
---Complex[0xbf80c380](0 + i * 0)
|
|
---Complex[0xbf80c370](0 + i * 0)
|
|
---Complex[0xbf80c360](0 + i * 0)
|
|
---Complex[0xbf80c350](2 + i * 0)
|
|
---Complex[0xbf80c340](1 + i * 0)
|
|
(24) ---Complex[0xbf80c330](0 + i * 0)
|
|
|
|
|
|
Remarques :
|
|
1-10 - Chaque element du tableau est initialisé par le constructeur par
|
|
defaut.
|
|
|
|
11 - Un objet temporaire est cree.
|
|
12 - Cet objet est affecté a la case courante du tableau.
|
|
13 - L'objet temporaire est detruit.
|
|
|
|
14-24 - Chaque element du tableau est passé au destructeur.
|
|
|
|
|
|
|