Source code explanation


Contents

Source code usage
Generalities
What is in the zip file ?

RTTI (RunTime Type Information)
Reference counting and smart pointers
Maths : vectors, matrices, quaternions
autoexp.dat file


Source code usage

Some usual words :
you can use the provided source code the way you want, in any software. It comes directly from my own programs and has been generally tested more than once. However you use it at your own risks, I am not liable for any possible damage that could happen. If you find some bugs, thanks for reporting them to this address.


Generalities

- This page explains how to use the provided sources, when the implemented notions are already known : it is not aimed at describing what is for example a smart pointer and why it is useful, but how to use my CSmartPtr template in your programs.

- I had the habit of prefixing my functions' names by the type of the value they return (example: HRESULT hrDoThis(...)) when I wrote this code. No need to tell me it's a good or bad one ;)

- Every .cpp file includes stdafx.h, in case it is used in a library or a program based on the 'precompiled headers' mechanism of Visual C++. If this is not your case, you only have to create an empty stdafx.h file in the same directory to avoid having to remove the #include statements.

- Some files use debugging macros, that are part of a system I have the intention to review, and which is not provided at the time being. So they are defined in the debug.h file as doing nothing, it's up to you to modify them so that they do some testing or write to a log file, etc.


What is in the zip file ?

At the time being this file contains classes for :
- RTTI (RunTime Type Information)
- reference counting and smart pointers
- maths : 2D / 3D / 4D vectors, 3*3 / 4*4 matrices, quaternions
- the autoexp.dat file modifying the way these classes are displayed in the Visual C++ debugger


RTTI (RunTime Type Information)

The use of the RTTI macros is briefly explained in the file itself (RTTI.h), and is the following :

- a 'root' class (= not derived from another class that supports RTTI) needs to contain the _ROOT_ macros :
in the .h file (example: Base.h) :
#include "RTTI.h"
class CBase
  {
  _DECLARE_ROOT_RTTI_;
  ...
  };
in the .cpp file (example: Base.cpp) :
#include "Base.h"
_IMPLEMENT_ROOT_RTTI_(CBase);
...
- a derived class needs to have the other macros :
in the .h file (example: Derived.h) :
#include "Base.h"
class CDerived : public CBase
  {
  _DECLARE_RTTI_;
  ...
  };
in the .cpp file (example: Derived.cpp) :
#include "Derived.h"
_IMPLEMENT_RTTI_(CDerived,CBase);
...

Once these macros are added to your classes, you can use the following instructions :
- if(_IS_EXACT_CLASS_(CDerived,pObj)) ...
returns true only if pObj points to an object of type CDerived.
- if(_IS_KIND_OF_(CBase,pObj)) ...
returns true if pObj points to an object of type CBase or of a derived class (ex: CDerived).
- _STATIC_CAST_(CBase,pObj)
casts the pointer pObj to CBase*
- _DYNAMIC_CAST_(CBase,pObj)) ...
casts the pointer pObj to CBase* only if pObj points to an objet of a CBase-derived class
(otherwise: returns NULL)

Each class using RTTI owns a static member of type CRTTI, containing the name of the corresponding class. This string can serve as a ClassID, each class name being unique in C++ (unless you use namespaces).


Reference counting and smart pointers

For objects of a class to be able to be referenced by smart pointers, it is required that :
- this class derives from CRefCount (reference counting)
- an instance of the CSmartPtr template has been defined for this class (for example by using the CSmartPointer macro)

This leads to writing this in the .h file :
#include "RefCount.h"
#include "SmartPtr.h"
class CExample : public CRefCount
  {
  ...
  };
CSmartPointer(CExample);
The CSmartPointer macro creates a CExamplePtr type corresponding to a "smart pointer to CExample", that is to be used this way :
CExamplePtr spPtr = new CExample
spPtr->DoSomething();
CExample* pObj2 = new CExample;
pObj2->DoSomething();
spPtr = pObj2;
spPtr->DoSomeOtherThing();
spPtr = NULL;
In the previous code excerpt :
- an object of type CExample is created, and pointed to by the smart pointer spPtr
- the function DoSomething of this object is called
- another object is created, and pointed to by a 'normal' pointer pObj2
- the function DoSomething of pObj2 is called (you see that the use is the same as with the smart pointer)
- pObj2 is assigned to spPtr : this has the effect of destroying the 1st object, because it is not pointed to by anybody anymore
- the function DoSomeOtherThing is called for the 2nd object using the smart pointer
- spPtr is set to NULL : the reference counter of the 2nd object is decremented, it is equal to zero, the object is destroyed

The two objects have been destroyed without any explicit call to delete, because the smart pointers are responsible for this. Notice that pObj2 then points to an invalid address : this is the danger of mixing 'normal' pointers with smart pointers ; in the above sample it is easy to replace pObj2 by a smart pointer so that the pointed object has a reference counter equal to 2 after spPtr = pObj2, then to 1 after spPtr = NULL, and that it is not deleted as long as pObj2 does not receive another value.

In theory a smart pointer can only point to objects created by 'new' because they are destroyed with 'delete'. However if you need to point to an object allocated on the heap with a smart pointer, you can avoid the call to delete with the function vSetAutoDelete(false) :
{
CExample HeapObject;
CExamplePtr spPtr = &HeapObject;
...
spPtr->vSetAutoDelete(false);
}
The last instruction will prevent delete from being called for HeapObject (when the closing bracket is reached, spPtr is destroyed and the reference counter of the pointed object is decremented, so that would be the normal behaviour).


Maths : vectors, matrices, quaternions

The reading of the two .h files (VectMat.h and Quaternion.h) should be enough to understand how to use the different classes. Most operators are overriden, but those who prefer it can call the C functions directly. At the time I wrote these sources, I saw no difference in speed between the two methods , or with completely inlined operators (that's why the inline functions call the C functions after all).


autoexp.dat file

Replace this file in your Developer Studio subdirectory Common\MSDev98\Bin, and it will change the way instances of the above classes are displayed in the 'watch' window of the debugger.
You can read how it works in the file itself, and add your own types and classes, it's very convenient !


back to top