Explication du code source
Table des matières
Utilisation du code source
Généralités
Contenu du fichier zip
RTTI (RunTime Type Information)
Comptage de références et smart pointeurs
Maths : vecteurs, matrices, quaternions
Fichier autoexp.dat
Utilisation du code source
Tou d'abord, la mise en garde habituelle :
vous pouvez utiliser le code source fourni comme bon vous semble, dans quelque programme que ce soit. Il provient directement de mes
propres applications et a de ce fait en général été testé plus d'une fois. Son utilisation se fait cependant
à vos risques et périls,
je ne pourrai en aucun cas être tenu responsable d'éventuels dommages occasionnés. Si vous découvrez des bugs, merci de me les signaler à
cette adresse.
Généralités
- Cette page explique comment utiliser les sources fournis, à condition de connaître les notions implémentées : elle n'a pas pour but de
décrire ce qu'est par exemple un smart pointeur et à quoi il sert, mais comment utiliser mon template CSmartPtr dans vos programmes.
- J'avais l'habitude de préfixer les noms de mes fonctions par le type de la valeur qu'elles retournent (exemple: HRESULT hrFaitCeci(...)) lorsque
j'ai écrit ce code. Inutile de me dire que c'est bien ou mal ;)
- Tous les fichiers .cpp incluent stdafx.h, au cas où ils seraient utilisés dans une librairie
ou une application faisant appel aux 'precompiled headers' de Visual C++. Si ce n'est pas votre cas, il vous suffit de créer un fichier
stdafx.h vide dans le même répertoire pour éviter d'avoir à supprimer les #include.
- Certains fichiers utilisent des macros de débuggage, qui font partie d'un système que j'ai l'intention de revoir et qui n'est pas fourni
pour l'instant. Elles sont donc définies dans le fichier debug.h comme ne faisant rien,
libre à vous de les modifier pour qu'elles effectuent les tests adéquats, écrivent dans un fichier de logs, etc.
Contenu du fichier zip
Ce fichier contient à l'heure actuelle des classes de :
- RTTI (RunTime Type Information)
- comptage de références et smart pointeurs
- maths : vecteurs 2D / 3D / 4D, matrices 3*3 / 4*4, quaternions
- le fichier autoexp.dat modifiant l'affichage de ces classes dans le debugger Visual C++
RTTI (RunTime Type Information)
L'utilisation des macros de RTTI est expliquée brièvement dans le fichier lui-même (RTTI.h),
et est la suivante :
- une classe 'racine' (= ne dérivant d'aucune autre classe qui utilise le système de RTTI) doit contenir
les macros _ROOT_ :
fichier .h (exemple: Base.h) :
#include "RTTI.h"
class CBase
{
_DECLARE_ROOT_RTTI_;
...
};
fichier .cpp (exemple: Base.cpp) :
#include "Base.h"
_IMPLEMENT_ROOT_RTTI_(CBase);
...
- une classe dérivée doit posséder les autres macros :
fichier .h (exemple: Derivee.h) :
#include "Base.h"
class CDerivee : public CBase
{
_DECLARE_RTTI_;
...
};
fichier .cpp (exemple: Derivee.cpp) :
#include "Derivee.h"
_IMPLEMENT_RTTI_(CDerivee,CBase);
...
Une fois ces macros ajoutées à vos classes, vous pouvez utiliser les instructions suivantes :
- if(_IS_EXACT_CLASS_(CDerivee,pObj)) ...
renvoie true uniquement si pObj pointe un objet de type CDerivee.
- if(_IS_KIND_OF_(CBase,pObj)) ...
renvoie true si pObj pointe un objet de type CBase ou d'une classe dérivée (ex: CDerivee).
- _STATIC_CAST_(CBase,pObj)
caste le pointeur pObj en CBase*
- _DYNAMIC_CAST_(CBase,pObj)) ...
caste le pointeur pObj en CBase* uniquement si pObj pointe un objet d'une classe dérivée de CBase
(sinon: renvoie NULL)
Chaque classe utilisant le RTTI possède un membre statique de type CRTTI, contenant le nom de la classe
en question. Cette chaîne de caractères peut servir de ClassID, chaque nom de classe étant unique en C++ (sauf utilisation de
namespaces).
Comptage de références et smart pointeurs
Pour que les objets d'une classe puissent être référencés par des smart pointeurs, il faut :
- que cette classe dérive de CRefCount (comptage de références)
- qu'une spécialisation du template CSmartPtr ait été définie pour cette classe (par exemple en utilisant la macro CSmartPointer)
Ceci revient à écrire dans le fichier .h :
#include "RefCount.h"
#include "SmartPtr.h"
class CExemple : public CRefCount
{
...
};
CSmartPointer(CExemple);
La macro CSmartPointer crée un type CExemplePtr correspondant à un "smart pointeur de CExemple",
qui s'utilise ainsi :
CExemplePtr spPtr = new CExemple
spPtr->FaitQuelqueChose();
CExemple* pObj2 = new CExemple;
pObj2->FaitQuelqueChose();
spPtr = pObj2;
spPtr->FaitAutreChose();
spPtr = NULL;
Dans l'extrait de code précédent :
- un objet de type CExemple est créé, et pointé par le smart pointeur spPtr
- la méthode FaitQuelqueChose de cet objet est appelée
- un autre objet est créé, et pointé par un pointeur 'classique' pObj2
- la méthode FaitQuelqueChose de pObj2 est appelée (on voit que l'utilisation est la même qu'avec le smart pointeur)
- pObj2 est affecté à spPtr : ceci a pour effet de détruire le 1er objet, puisqu'il n'est plus pointé par personne
- la méthode FaitAutreChose est appelée pour le 2ème objet via le smart pointeur
- spPtr est mis à NULL : le compteur de références du 2ème objet est décrémenté, il vaut zéro, l'objet est détruit
Les deux objets ont été détruits sans aucun appel explicite à delete, puisque ce sont les smart pointeurs qui s'en chargent. Notez que
pObj2 pointe alors une adresse invalide : c'est le danger de mélanger des pointeurs 'normaux' avec des smart pointeurs ; dans l'extrait
ci-dessus il suffit de remplacer pObj2 par un smart pointeur pour que l'objet pointé ait un compteur de références égal à 2 après
spPtr = pObj2, puis à 1 après spPtr = NULL, et qu'il ne soit pas détruit tant que pObj2 ne reçoit pas une autre valeur.
En théorie un smart pointeur ne peut pointer que des objets créés par new puisqu'ils sont détruits avec delete. Si toutefois vous avez besoin
de pointer un objet du tas (heap) avec un smart pointeur, vous pouvez éviter l'appel à delete avec la fonction
vSetAutoDelete(false) :
{
CExemple HeapObject;
CExemplePtr spPtr = &HeapObject;
...
spPtr->vSetAutoDelete(false);
}
La dernière instruction évitera que delete ne soit appelé pour HeapObject (lorsque l'accolade fermante est atteinte, spPtr est détruit et
le compteur de références de l'objet qu'il pointe est décrémenté, donc c'est ce qui se produirait normalement).
Maths : vecteurs, matrices, quaternions
La lecture des deux fichiers .h (VectMat.h et Quaternion.h) devrait suffire à
comprendre l'utilisation des différentes classes. La plupart des opérateurs sont surchargés, mais ceux qui le préfèrent peuvent appeler
directement les fonctions C. A l'époque où j'ai écrit ces sources je n'ai pas constaté de différence de vitesse entre les deux méthodes, ou
avec des opérateurs complètement inlinés (c'est pourquoi les fonctions inline appellent en fin de compte les fonctions C).
Fichier autoexp.dat
Remplacez ce fichier dans votre sous-répertoire Common\MSDev98\Bin de Developer Studio,
et il modifiera la façon dont les instances des classes ci-dessus sont affichées dans la fenêtre 'watch' du debugger.
Vous pouvez lire comment cela fonctionne dans le fichier lui-même, et ajouter vos propres types et classes, c'est très pratique !
haut de la page