Pass an array of objects into a function

This has been bugging me for some time now..
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
    #include <iostream>

    using namespace std;

    enum ActorType { PC, NPC };

    class Player
    {
        public:
            void set_Stats(string a, int b, int c) { Name = a; HP = b; HPM = c; }
            string get_Name() const { return Name; }
            int get_HP() const      { return HP;   }
            int get_HPM() const     { return HPM;  }
        private:
            string Name;
            int HP;
            int HPM;
    };

    void SomeFunc(string Name, int HP, int HPM);

    int main()
    {
        Player ACT[2][2];
        ACT[PC] [0].set_Stats("Guy"      , 24, 24);
        ACT[PC] [1].set_Stats("Kid"      , 20, 20);
        ACT[NPC][0].set_Stats("Goblin"   , 12, 12);
        ACT[NPC][1].set_Stats("MrFiddler", 35, 35);

        /// There must be a better way to do this!
        SomeFunc(ACT[PC][0].get_Name(), ACT[PC][0].get_HP(), ACT[PC][0].get_HPM());
    }

    void SomeFunc(string Name, int HP, int HPM)
    {
        // Stuff..
    }

I want to be able to pass an entire array of objects into any given function. I tried doing SomeFunc(Player ACT); and void SomeFunc(Player *ACT){} but that doesn't work. It's such a pain doing it the way shown above, not to mention how much space it takes / how messy it looks.

I want to know how to do this so that I can create all of my (initial) objects for all of my classes in one neat space, then send them wherever they're needed. If there's a completely different way to get around this problem, you can post that too. Thanks!
You can pass it as an array like this:
Note that this uses a bit of pointer magic: make sure you read up how pointers and arrays interact (about half way down):
http://www.cplusplus.com/doc/tutorial/pointers/

Also, don't forget to delete the allocated memory when you're finished, or you'll get memory leaks.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
int main()
{
    // Declare the array
    // This is a pointer to an array of pointers with two members
    Player** playerArray = new Player*[2];
    // Each member points to an array of 100 players.
    playerArray[PC] = new Player[100];
    playerArray[NPC] = new Player[100];

    // Populate the array
    for( int i = 0; i < 100; i ++)
    {
        playerArray[PC][i].set_Stats(  "Playable Character", i+10, 1+20);
        playerArray[NPC][i].set_Stats( "Not Playable Character", i+5, 1+5);
    }

    // Pass the array
    SomeFunc( playerArray);
    system("pause");
}

void SomeFunc( Player** playerArray)
{
    // Do stuff with the passed array
    for( int i = 0; i < 100; i ++)
    {
        cout << playerArray[PC][i].get_Name() << "\t " << i << " has " << playerArray[PC][i].get_HP() << "\t / " << playerArray[PC][i].get_HPM() << "\tHP." << endl;
    }
    for( int i = 0; i < 100; i ++)
    {
        cout << playerArray[NPC][i].get_Name() << "\t " << i << " has " << playerArray[NPC][i].get_HP() << "\t / " << playerArray[NPC][i].get_HPM() << "\tHP." << endl;
    }
}
This looks great, I'm glad to find that there's an elegant solution here.

1
2
3
4
5
6
    // Declare the array
    // This is a pointer to an array of pointers with two members
    Player** playerArray = new Player*[2];
    // Each member points to an array of 100 players.
    playerArray[PC] = new Player[100];
    playerArray[NPC] = new Player[100];

This is what confuses me though, the first line in particular. I don't understand why or when you need to use ** instead of just a single *. I guess I need to brush up on a couple of things.
This is an integer pointer:
 
int * i

This is a pointer, which points to an integer pointer:
 
int ** i

Since the special relationship between pointers and arrays, above could be an array of integer pointers too, like so:
1
2
3
4
int ** i;
i = new int * [5] // i is now an array of 5 integer pointers.
i[0] -> first integer pointer
i[1] -> second integer pointer.

Since each element of "i" array are also pointers themselves, they could also be arrays, like so:
1
2
3
4
i[0] = new int[10];
i[1] = new int[20];
i[2] = new int[30];
// etc. 

Now, you can accces your integers like this:
1
2
i[0][1] = 5;
i[1][3] = 7;

Effectively, you have a 2 dimensional array here.
Last edited on
This is great guys, thanks for the explanations.
closed account (S6k9GNh0)
I'm rather confused.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>

template <typename T>
struct MyStruct
{
    T a_variable; //bleh but it's good for example
};

template<size_t size, typename T>
void myFunc(T* array)
{
    for (unsigned int i = 0; i < size; ++i)
        std::cout << array[i].a_variable << " ";

    std::cout << std::endl;
}

int main()
{
    MyStruct<int> myArray[3] = {}; //ah, beautiful and obfuscated C syntax
    myArray[0].a_variable = 1;
    myArray[1].a_variable = 2;
    myArray[2].a_variable = 3;
    myFunc<3>(myArray);
    return 0;
}


What's wrong with this?
What's wrong with this?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>

template <typename T>
struct MyStruct
{
    T a_variable; //bleh but it's good for example
};

template<size_t size, typename T>
void myFunc(T* array)
{
    for (unsigned int i = 0; i < size; ++i)
        std::cout << array[i].a_variable << " ";

    std::cout << std::endl;
}

int main()
{
    MyStruct<int> myArray[3] = {}; //ah, beautiful and obfuscated C syntax
    myArray[0].a_variable = 1;
    myArray[1].a_variable = 2;
    myArray[2].a_variable = 3;
    myFunc<3>(myArray);
    return 0;
}

I'm rather confused.
closed account (S6k9GNh0)
The point (no pun intended) was that there is no need for excessive use of pointers. An array can be represented with a basic singular-dimension pointer. Even when allocating on the heap, only a single-dimension pointer or reference is needed. Doing otherwise adds needless confusion and complication.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>

template <typename T>
struct MyStruct
{
    T a_variable; //bleh but it's good for example
};

template<size_t size, typename T>
void myFunc(T* array)
{
    for (unsigned int i = 0; i < size; ++i)
        std::cout << array[i].a_variable << " ";

    std::cout << std::endl;
}

int main()
{
    MyStruct<int>* myArray = new MyStruct<int>[3]; //Eh, no way to initialize this here without constructor
    myArray[0].a_variable = 1;
    myArray[1].a_variable = 2;
    myArray[2].a_variable = 3;
    myFunc<3>(myArray);
    return 0;
}
Last edited on
Does your example work for a 2D array? What would the function take as an argument so that I could access any of the arrays elements inside of the function (and change them)?
Last edited on
closed account (S6k9GNh0)
The point I was making is that 2D arrays tend to be overrated. No, you can't pass a 2D array in this case simply because not enough data is passed to figure out the size of the array. While I could change my function and struct to account for such data, I'm trying to explain that doing as such is redundant, inflexible, error-prone, and should probably be avoided.

Why do you want a 2D array?

Rather, as an alternative solution to your use of the 2D array, I would suggest doing some basic math like so:

1
2
3
4
Actor[PC+1].set_Stats(/*blah*/); 
//This basic math is generally deduced at compile time anyways so generally no overhead unless you use a compiler from the 80s.
SomeFunc(Actor + (PC + 1));
 
Last edited on
Topic archived. No new replies allowed.