Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 9 of 9
  1. #1
    New to the CF scene
    Join Date
    Aug 2009
    Posts
    5
    Thanks
    1
    Thanked 0 Times in 0 Posts

    How to pass arrays of objects to function in c++?

    Hi!

    I'm fairly new to this whole programming business but I'm getting there... slowly

    What I'm trying to do is to send an array of objects to a function and have this function access one of the objects memberfunctions. This is pretty much what I have (I've cut away some code so it'll be easier to follow and some stuff thats not finished).

    I've highlighted the portions where I think I got things wrong but don't know what.

    in header file GameHost.h

    Code:
    #include "Die.h" // forward declaration of class Die 
    #include "GameIO.h" // forward declaration of class GameIO
    
    
    /**
     * class GameHost starts a round of dice, is responsible for letting
     * the player roll his/her dice and keeping track on when the round is over
     * and more...
     **/
    class GameHost
    {
        public:
        GameHost(); // constructor for Game host class
        ~GameHost(); // destructor for Game host class -- preforms house keeping, cleans allocated memory
    
        int startRound(); // Starts round of the game
    
        void rollDice(); // rolls all dice the player has and calls the choose Dice
                            // function if appropriate
        void rollDice( int diceToRoll[] ); // Overloaded version of rollDice which
                                                  // takes an array specifying which dice to roll
    
        void chooseDice(); // lets the player choose which die/dice if any to roll
    
        void endRound(); // Ends the round and resets members for a new round
    
        static const int nDice = 5; //contains the number of dice in the game
    
    
        private:
        Die* Dice; // creates an array with five (5) Die objects
        // is there a problem with my declaration of the array with Die objects?
    
        GameIO myIO; // creates a I/O object
    
        int numberOfRolls; // keeps track of number of rolls during the round
        int rollsInRound; // decides how many rolls there should be in a round 
                              // (including first roll and x number of re-rolls)
    
        int* chooseDie( int nReroll ); // support function that prompts the user to 
                                               // choose a die to re-roll,
                                               // takes the number of dice to re-roll as 
                                               // argument and returns an array with the
                                               // chosen dice
    
    }; // end class GameHost
    in cpp-file GameHost.cpp:

    Code:
    /**
     * constructor for Game Host class - initializing array Dice
     **/
    GameHost::GameHost()
    {
        // Dice contains an array with pointers to Die objects
        Dice = new Die[ nDice ]; // create space in memory for an array of Die objects
        // should I initialize this in a different manner? Is there an other way?
    
        rollsInRound = 3; // decides how many rolls there should be in a round (including first roll and x number of re-rolls)
    
        numberOfRolls = 0; // initialize numberOfRolls to 0
    
    } // end constructor GameHost
    
    
    /**
     * destructor for Game Host class - preforms housekeeping and cleans allocated memory resources
     **/
    GameHost::~GameHost()
    {
        delete [] Dice; // give back memory space occupied by array of Die objects - Dice
    
    } // end destructor GameHost
    
    
    /**
     * startRound() starts a round of dice by rolling all dice (through rollDice)
     **/
    int GameHost::startRound()
    {
        rollDice(); // start of round by rolling dice
    
        return 0; // when round ends startRound return 0 to caller
    
    } // end startRound
    
    
    /**
     * rollDice rolls all the dice and prints them for user then decides whether to continue round or end it.
     **/
    void GameHost::rollDice()
    {
    
        // loop through the dice in array Dice and roll each once
        for ( int i = 0; i < nDice; i++ )
        {
            Dice[ i ].rollDie(); // roll the dice in array Dice by 
                                    // using the Die objects member function rollDie()
                                    // this stores a value between 1-6 in the die object
                                   
    
        }
    
        // print the dice through the gameIO
        myIO.printDice( &Dice, nDice ); 
        /** this call is where things starts to go wrong
           * I believe it's correct to send it like that??
           * I've also tried sending it by value without '&' but then
           * the compiler won't recognize the call (but I guess thats
           * because I've written it the way I have).
           **/ 
    
        numberOfRolls++; // increment numberOfRolls since dice have been rolled and printed
    
        // if player have rolled three times (first roll and two rerolls)
        if ( numberOfRolls == rollsInRound )
        {
            endRound(); // end round
    
        }
        else
        {
            chooseDice(); // choose which die/dice to reroll next
    
        }
    
    } // end rollDice
    
    
    /**
     * endRound() ends the round of dice and resets the numberOfRolls so  
     * game host is ready for a new round
     **/
    void GameHost::endRound()
    {
        numberOfRolls = 0; // Reset number of Rolls
    
    } // end endRound
    in header-file GameIO.h

    Code:
    #include <string>
    using namespace std;
    
    #include "Die.h"
    
    
    // handles input and output in a game of Dice
    class GameIO
    {
        public:
        GameIO ();
         // Overloading function printText -- one for char and one for strings
    
        void printText( const string& stringPtr); // Receives a reference to a string. 
                                                              // Prints it without touching it.
        void printText( const char* stringPtr); // Receives pointer to a character 
                                                            // string. Prints it without 
                                                            // modifications.
    
        void printInt( const int& intPtr); // takes a reference to an int and prints it.
    
        // printDice takes an array of pointers to Die objects 
        // and prints a line of die illustrations with eyes corresponding to the 
        // values gathered from the dice. 
        // Also takes the number of dice as argument as an int
        void printDice( Die* diceArray[], const int numberOfDice );
    
           // this is the problematic function
        
        void printColumns( int nCols ); // prints new lines and tabs in  a sequence 
                                                 // allowing for output of text in columns
                                                 // takes an int (representing the number of
                                                 // columns) as argument
    
        int getInt(); // fetches int from user and sends it back to caller, also
                         // checks if data input is really int
    
        private:
        int columnCounter; // helps printColumns to know where columns and
                                  // newlines starts
    };
    in cpp-file gameIO.cpp

    Code:
    #include <iostream>
    using namespace std;
    
    #include "GameIO.h"
    
    /**
     * Constructor for game I/O
     **/
    
    GameIO::GameIO()
    {
        columnCounter = 1; // initialize columnCounter
    }
    
    /**
     * printDice takes an array of ints (with each element in the array representing
     * the faces of the dice to be printed) and an int (representing the number of dice)
     * as arguments and prints a row of dice corresponding to the ints received.
     * Se exampel below.
     **/
    
    /****************************************
     *                --::EXAMPLE::--                               
     *             output from printDice                             
     *    -------  -------  -------  -------  -------          
     *    |     |  | *   |  | *   |  | * * |  | * * |              
     *    |  *  |  |     |  |  *  |  |     |  |  *  |              
     *    |     |  |   * |  |   * |  | * * |  | * * |              
     *    -------  -------  -------  -------  -------          
     *                                                                       
     ******************************************/
    void GameIO::printDice( Die* diceArray[], const int numberOfDice )
    {
    // this function is the problem !!
    
        int diceToPrint[ numberOfDice ]; // array to store the dice to print as an
                                                    //  int representing the eyes of the dice
    
        // get values from Dice
        for( int i = 0; i < numberOfDice; i++ )
        {
            // calls the member funciton of class Die called getDieValue(); which
            // returns an int representing the result form the latest roll of the die
            // and stores the value in array diceToPrint.
    
            diceToPrint[ i ] = diceArray[ i ].getDieValue(); 
    
            // the compiler gives following error for this line:
    request for member `getDieValue' in `*((+(((unsigned int)i) * 4u)) + diceArray)', which is of non-class type `Die*'
        }
    
        /** Die pieces **/
        // makes upp the illustrations
        const string topDie = "-------";
        // Bottom and top of the die looks the same.
        // but different (specific) names makes it easier to read.
        const string bottomDie = "-------";
        const string sidesDie = "|     |";
        const string oneEye = "|  *  |";
        const string twoEyes = "| * * |";
        const string sideEyeLeft = "| *   |";
        const string sideEyeRight = "|   * |";
        /** end die pieces **/
    
        const int numberOfFaces = 6; // contains the number of faces on the die
        const int numberOfPieces = 3; // contains the number of pices for each die illustration
    
        // diceArray with 6 rows (number of faces on a die) and 5 columns
        // (number of pieces every face is built of)
        const string diceArray[ numberOfFaces ][ numberOfPieces ] = {
            { sidesDie   , oneEye  , sidesDie     },   // one eye
            { oneEye     , sidesDie, oneEye       },   // two eyes
            { sideEyeLeft, oneEye  , sideEyeRight },   // three eyes
            { twoEyes    , sidesDie, twoEyes      },   // four eyes
            { twoEyes    , oneEye  , twoEyes      },   // five eyes
            { twoEyes    , twoEyes , twoEyes      }    // six eyes
            }; // end diceArray
    
        /**  start printing dice illustrations  **/
    
        // print the top of the illustrations.
        // All the pieces of the first row of the illustrations should always be the same
        for ( int j = 0; j < numberOfDice; j++ )
        {
            printText( topDie ); // print the top piece of every die
            printColumns( numberOfDice ); // print the pieces in five columns
        }
    
    
        // from the top left startprinting from diceArray
        // loop through columns of diceArray
        for( int k = 0; k < numberOfPieces; k++ )
        {
            // loop through the rows of diceArray
            for( int l = 0; l < numberOfDice; l++ )
            {
                 // print the die piece in the specified element
                printText( diceArray [ diceToPrint[ l ] - 1 ][ k ]);
                printColumns( numberOfDice ); // print dice in five columns
                 // there might be a problem here too, but I'm not sure ?!
    
            } // end inner for
        } // end outer for
    
        // print the bottom of the illustrations.
        // All the pieces of the last row of the illustrations should always be the same
        for ( int m = 0; m < numberOfDice; m++ )
        {
            printText( bottomDie ); // print the bottom piece of every die
            printColumns( numberOfDice ); // print the pices in five columns
        }
    
        /** End printing Die illustrations **/
    
    } // end function printDice
    // end of problematic function
    I've taken away the definitions of most of the member functions in gameIO since I know they work (they are pretty much just using cout and cin to do their job). The printDice function worked before when I was just feeding it with an array of integers. Where each integer represented the number of eyes on the die. The problem started when I tried to rewrite the function to take an array of objects instead.

    This gets long really quickly I hope someone is able and has the energy to help.

    /Chris
    Last edited by SirSkorpan; 08-29-2009 at 12:25 PM. Reason: changed heading and notification, fixed some of the spelling, resolved

  • #2
    Regular Coder BrickInTheWall's Avatar
    Join Date
    Mar 2009
    Location
    Munich, Germany
    Posts
    139
    Thanks
    1
    Thanked 13 Times in 13 Posts
    Well I'm too lazy to go through your code, but I'd try this (I mainly code in C# so sorry if I'm causing memory leaks, but I think its fine):

    Code:
    #include <iostream>
    
    using namespace std;
    
    class MyClass
    {
    public:
    	int _x;
    
    	MyClass(int x)
    	{
    		_x = x;
    	}
    
    	MyClass()
    	{
    		_x = 20;
    	}
    };
    
    void AccessObjX(MyClass *pObj, int size)
    {
    	MyClass *tempObjArray = new MyClass[size];
    	MyClass *deletePointer = tempObjArray;
    	tempObjArray = pObj;
    	delete deletePointer;
    	deletePointer = 0;
    	
    	for (int i = 0; i < size; i++)
    	{
    		cout << tempObjArray[i]._x << endl;
    	}
    
    	tempObjArray[0]._x = 30;
    }
    
    int main(void)
    {
    	MyClass myObj[2];
    	myObj[1]._x = 10;
    	AccessObjX(myObj, sizeof(myObj) / sizeof(MyClass));
    	cout << myObj[0]._x;
    
    	int endP;
    	cin >> endP;
    	return 0;
    }
    The only reason why I'm allocating memory in the function is because I want to create a temporary array of variable size. You don't really need deletePointer but I feel it puts emphasis on it.

    edit: hah I did mess up. You're going to need delete[] instead of delete, sorry. If I keep it the way it is now, I'm only deleting part of what I allocated.
    Last edited by BrickInTheWall; 08-29-2009 at 02:06 AM.

  • Users who have thanked BrickInTheWall for this post:

    SirSkorpan (08-29-2009)

  • #3
    New to the CF scene
    Join Date
    Aug 2009
    Posts
    5
    Thanks
    1
    Thanked 0 Times in 0 Posts
    I found the problem.

    In the failing function I had done this


    Code:
    printDice( Die *diceArray, const int numberOfDice )
    {
        int dieValue[ numberOfDice ];
    
        for( int i = 0; i < numberOfDice; i++ )
        {
            dieValue[ i ] = diceArray[ i ].getDieValue();
        }
    
        const string diceArray[6][3] = {.......}
    }
    So I had given the array I received in the function call the same name as another array I declared and initialized in the function. changed the name of the one received and now it works.

    Great little walk-through on how you do it, thank you! It made me have to look through all of my code after reading your post cuz I felt we were doing pretty much the same thing.

    But I understand why you didn't check all of my code It gets long quickly. Next time I think I need to make it a lot shorter.

    Thank you!
    /Chris

  • #4
    Regular Coder BrickInTheWall's Avatar
    Join Date
    Mar 2009
    Location
    Munich, Germany
    Posts
    139
    Thanks
    1
    Thanked 13 Times in 13 Posts
    Yea yours works fine and is probably its better to use const to initialize the array, rather than allocate memory on the heap. Just note mine causes a memory leak right now.
    Last edited by BrickInTheWall; 08-29-2009 at 04:21 PM.

  • #5
    New to the CF scene
    Join Date
    Aug 2009
    Posts
    5
    Thanks
    1
    Thanked 0 Times in 0 Posts
    As said, I'm new so, I'm eager to learn. I'm trying to figure out this memory leak you were talking about. (We just had pointers in class so I thought of it as good practice). Have I gotten this correctly? (see comments in code below)

    Code:
    void AccessObjX(MyClass *pObj, int size)
    {
    	MyClass *tempObjArray = new MyClass[size]; // here you allocate memory for an array 
                                                       // of MyClass-objects (of variable 
                                                       // length/size) 
    
    	MyClass *deletePointer = tempObjArray; // creates another array which now points to 
                                                   // the same memory as tempObjArray
    
    	tempObjArray = pObj; // tempObjArray now points to same memory as pObj so 
                                 // tempObjArray and deletePointer nolonger points to 
                                 // same memory, right?
    
    	delete [] deletePointer; // deletePointer nolonger points to a specific place in 
                                     // memory but can point to pretty much anything in memory?
                                     // I took the liberty to ad the []-operator  :)
    
    	deletePointer = 0; // so you set deletePointer be a NULL pointer
    	
           // prints the values of _x for each MyClass-object in the tempObjArray
    	for (int i = 0; i < size; i++)
    	{
    		cout << tempObjArray[i]._x << endl;
    	}
    
    	tempObjArray[0]._x = 30; // assign 30 to _x in first MyClass-object of tempObjArray
    
    // should you here delete tempObjArray as well? To prevent memory leak, as such:
            delete [] tempObjArray; // tempObjArray nolonger points to any specific memory
            tempObjArray = 0; // tempObjArray is now NULL pointer
    }
    Code:
    int main(void)
    {
        MyClass myObj[2]; //creates an array with two objects
        myObj[1]._x = 10; // sets _x of second object in array
        
        AccessObjX(myObj, sizeof(myObj) / sizeof(MyClass)); // sizeof(myObj) gives number of bytes
                                                            // in array and sizeof(MyClass) gives
                                                            // number of bytes in a MyClass object
                                                            // division gives number of objects 
                                                            // in array
                                                            
        cout << myObj[0]._x; // acess and print _x of first element in array myObj
                          // (which were set to 30 before)
    
        int endP;
        cin >> endP;
        return 0;
    }
    Is it causing a memory leak because you don't delete the whole of the deletePointer array? Or do you also need to delete tempObjArray as well (as I tried in the code above). Or is there something else that I don't see?

    Thanks again!
    /Chris

  • #6
    Regular Coder BrickInTheWall's Avatar
    Join Date
    Mar 2009
    Location
    Munich, Germany
    Posts
    139
    Thanks
    1
    Thanked 13 Times in 13 Posts
    Using delete on tempObjArray should cause an exception to be thrown as it is not pointing to anything on the heap (so nothing that was allocated dynamically).
    Thats like doing the following:
    int myInt[3];
    // Initialize array.
    delete myInt;

    Also my mistake was using delete rather than delete[] on the deletePointer. If you use delete on a dynamically allocated array then they will be deleted but it can cause some weird behavior. You can't just delete part of an array, that doesn't work. But you might be deleting something else too.
    From what I have learned, using new[] (like in 'int *myInt = new int[2]'), C++ caches the amount of elements in the array somewhere, and when using delete[], it retrieves this amount, making sure you delete the correct amount of elements. I would double check this though as that explanation might be a bit vague. I hardly program in C++ anymore so I'm a bit rusty.

  • #7
    New to the CF scene
    Join Date
    Aug 2009
    Posts
    5
    Thanks
    1
    Thanked 0 Times in 0 Posts
    From what I have learned, using new[] (like in 'int *myInt = new int[2]'), C++ caches the amount of elements in the array somewhere, and when using delete[], it retrieves this amount, making sure you delete the correct amount of elements. I would double check this though as that explanation might be a bit vague. I hardly program in C++ anymore so I'm a bit rusty.
    Ah I get it, yes that goes pretty much in line with what our book says too. So yes then it was only the [] missing in the code. Thank you!

  • #8
    Regular Coder BrickInTheWall's Avatar
    Join Date
    Mar 2009
    Location
    Munich, Germany
    Posts
    139
    Thanks
    1
    Thanked 13 Times in 13 Posts
    Quote Originally Posted by SirSkorpan View Post
    Ah I get it, yes that goes pretty much in line with what our book says too. So yes then it was only the [] missing in the code. Thank you!
    I'm curious, what book are you reading? By saying "our book" are you learning to program at college or uni? Just wanna know what literature you're working with. I can never have enough books as references .

  • #9
    New to the CF scene
    Join Date
    Aug 2009
    Posts
    5
    Thanks
    1
    Thanked 0 Times in 0 Posts
    I'm studying at the Umea University in Sweden. The book we use is: "C++ how to program 6th ed" by Deitel. I think it's a really good book at least for me who hasn't programmed at all before taking this course (some java script but that barely counts).


  •  

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •