Jump to content
  • Advertisement
  • 06/24/00 01:25 PM
    Sign in to follow this  

    Modular Programming: A Classless Approach Part I

    General and Gameplay Programming

    Myopic Rhino
    [size="5"]Who is this written for?

    This series is for those who have decided the quirks of C++ classes are more trouble than they are worth. I intend to provide alternatives to certain features of classes that can be emulated using more traditional techniques. This article is not meant to be argumental, so I will not go into the 'why' of avoiding classes, rather I will assume you've read one of the many papers out there pointing out its many flaws and you've decided you would like to use them as little as possible. The format of this series will likely resemble that of this article; first bringing up a feature of classes that we can emulate, then going into the implementation, followed by any limitations of the approach.


    [size="5"]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 independent 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();
    }// 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 );
    }

    [size="5"]In Conclusion: The Good And The Bad

    As you can see, multiple instances of a module are possible despite what some will have you believe. Using this method, an array of a structure entitled _private takes the place of the private keyword, and in this case it actually is private, not sitting in the interface file for everyone to see like in the case of a class definition. The datatype M_Example is really just an int as an ID to be used as an index to the _private array. When you create an object using Example_CreateInstance, you're just reserving a spot in that array. You'll immediately notice two flaws to this approach I'm sure. First, the number of objects is limited to _MAXOBJECTS. Also, you can create an object, but you apparently can't destroy it. Well, that's where a linked list would come in handy. I only used an array to keep the idea clear, but if you were to use this method, using a linked list is the only way to go. Well, that's it for this article. Any questions, comments, flames, or new article ideas can be directed to godofarson@aol.com. Hopefully this article has sparked some ideas for you, if so let me know.


      Report Article
    Sign in to follow this  


    User Feedback


    There are no comments to display.



    Create an account or sign in to comment

    You need to be a member in order to leave a comment

    Create an account

    Sign up for a new account in our community. It's easy!

    Register a new account

    Sign in

    Already have an account? Sign in here.

    Sign In Now

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!