Object Instances
I once read that class based programming provides an advantage over ordinary modular programming in that the former allows multiple instances of objects that are completely independant of each other, while the latter doesn't have that support. Such blasphemy is the topic of this, the first article of the series. To begin, let's take a look at a simple class:
// let's say this is in c_example.h
class C_Example
{
public:
void Displayxy( void );
void Setx( int xValue );
void Sety( int yValue );
private:
int x;
int y;
};
// and this is in c_example.cpp
#include "c_example.h"
void C_Example::Displayxy( void )
{
cout << "x == " << x << '\n' << "y == " << y << '\n';
}
void C_Example::Setx( int xValue )
{
x = xValue;
}
void C_Example::Sety( int yValue )
{
y = yValue;
}
Now, declaring and using multiple instances might be done something like:
#include "c_example.h"
void main( void )
{
// create two instances of C_Example
C_Example inst1;
C_Example inst2;
// set x and y for the first instance
inst1.Setx( 5 );
inst1.Sety( 4 );
// set x and y for the second instance
inst2.Setx( 8 );
inst2.Sety( 9 );
// display contents of each
inst1.Displayxy();
inst2.Displayxy();
}
I'd like to point out here that while this example is extremely stupid and useless, I'm using it to make sure the ideas being discussed get through without any distractions. Now, on to the standard modular version:
// this might be in m_example.h
void Example_Displayxy( void );
void Example_Setx( int xValue );
void Example_Sety( int yValue );
// and this might be in m_example.cpp
#include "m_example.h"
static int _x;
static int _y;
void Example_Displayxy( void )
{
cout << "x == " << _x << '\n' << "y == " << _y << '\n';
}
void Example_Setx( int xValue )
{
_x = xValue;
}
void Example_Sety( int yValue )
{
_y = yValue;
}
// now to use the module:
#include "m_example.h"
void main( void )
{
// you cannot declare multiple instances with this approach.
// there is only one instance, which is the content of "m_example.cpp".
Example_Setx( 5 );
Example_Sety( 4 );
Example_Displayxy();
}
Now for the fun part. The example above clearly shows the reason why most people assume the only way to support multiple instances of an object is through classes. The alternate approach I'm going to give here uses an array to hold member data.
// the new "m_example.h"
// the m_example data type
typedef unsigned int M_Example;
// module interface functions
M_Example Example_CreateInstance( void );
void Example_Displayxy( M_Example objInst );
void Example_Setx( M_Example objInst, int xValue );
void Example_Sety( M_Example objInst, int yValue );
// the new "m_example.cpp"
#include "m_example.h"
#define _MAXOBJECTS 128
struct _PRIVATE
{
int x;
int y;
}static _private[ _MAXOBJECTS];
M_Example _curInstance = 0;
M_Example Example_CreateInstance( void )
{
_curInstance++;
return( _curInstance - 1 );
}
void Example_Displayxy( M_Example objInst )
{
cout << "x == " << _private[objInst].x << '\n'
<< "y == " << _private[objInst].y << '\n';
}
void Example_Setx( M_Example objInst, int xValue )
{
_private[objInst].x = xValue;
}
void Example_Sety( M_Example objInst, int yValue )
{
_private[objInst].y = yValue;
}
// and to use the new module:
#include "m_example.h"
void main( void )
{
// with the new module you can create more than one instance:
// create two instances of M_Example
M_Example inst1 = Example_CreateInstance();
M_Example inst2 = Example_CreateInstance();
// set x and y for the first instance
Example_Setx( inst1, 5 );
Example_Sety( inst1, 4 );
// then set x and y for the second instance
Example_Setx( inst2, 8 );
Example_Sety( inst2, 9 );
// display the contents of both
Example_Displayxy( inst1 );
Example_Displayxy( inst2 );
}
|