2
\$\begingroup\$

I tried to create an array Entity[] with elements Human and Zomby.

Entity ent[5];
ent[0].set("human");
ent[1].set("human");
ent[2].set("human");
ent[3].set("human");
ent[4].set("zomby");

or

Entity ent[5];
ent[0] = new Human();
ent[1] = new Human();
ent[2] = new Human();
ent[3] = new Zomby();
ent[4] = new Zomby();
delete[] ent;

They are in different classes because Human and Zomby need different ai functions. They are in the same array to compare them, like this:

for (int a = 0; a < entL; a++)
{
    for (int b = 0; b < entL; b++)
    {
        ent[a].ai( ent[b] ); // process ai interaction with other entities
    }
}

Is there a way for an array to have multiple types, or is there a better way to handle objects? Here's my example code:

class Entity // base class
{
public:
    float x, y;
};

class Human : public Entity // sub-class
{
public:
    void ai(Entity &n){}
};
class Zomby : public Entity // sub-class
{
public:
    void ai(Entity &n) {}
};

int main(int argc, char **argv)
{
    // create entities in one container
    const int entL = 5;
    Entity ent[entL];
    ent[0] = new Human();
    ent[1] = new Human();
    ent[2] = new Zomby();
    ent[3] = new Zomby();
    ent[4] = new Zomby();

    // inside game while-loop
    for (int a = 0; a < entL; a++)
    {
        for (int b = 0; b < entL; b++)
        {
            ent[a].ai( ent[b] ); 
        }
    }

    delete[] ent;

    system("PAUSE");
    return 0;
}

RESOLVED

I can make variants of functions in sub-classes like ai using virtual and override.

class Entity // base class
{
public:
    Position pos;
    virtual void ai(Position& other) { }

};

class Human : public Entity // sub-class
{
public:
    virtual void ai(Position& other) override {
        // human-specific AI code
    }
};

class Zomby : public Entity // sub-class
{
public:
    virtual void ai(Position& other) override {
        // zomby-specific AI code
    }
};

Entity* ent[5];
ent[0] = new Human (); // set sub-class elements
ent[1] = new Zomby ();
ent[2] = new Zomby ();
ent[3] = new Zomby ();
ent[4] = new Zomby ();

ent[0]->ai(ent[1]->pos); // call human.ai() passing zomby.pos

delete[]* ent;

Now, an array-pointer of a base-class can store elements of sub-classes.

\$\endgroup\$
0

2 Answers 2

2
\$\begingroup\$

When you have an array of type Entity then you can only call methods on the entries which are declared in the class Entity.

If you want Human and Zomby to have different implementations for that method, then you can declare that function as virtual in the Entity class. You can then override that implementation in both sub-classes. That means when you call the method .ai on an Entity the program checks what kind of entity it is and calls the corresponding method of the corresponding class.

Another thing you might want to consider is to pass the argument by reference instead of by value. When you pass objects by value, then you are creating a copy of the object in memory, pass that copy to the function and then discard that copy when the function finishes. But when you pass objects by reference, you are passing that object. This has two advantages:

  1. it's faster because the program doesn't need to create a copy of the object.
  2. You can do changes to the object in the function which are applied to the original object.

Example:

class Entity // base class
{
public:
    float x, y;
    virtual void ai(Entity& other) { }

};

class Human : public Entity // sub-class
{
public:
    virtual void ai(Entity& other) override {
           // human-specific AI code
    }
};

class Zomby : public Entity // sub-class
{
public:
    virtual void ai(Entity& other) override {
           // zomby-specific AI code
    }
};
\$\endgroup\$
1
  • \$\begingroup\$ This may work. If I use a pointer array of base-class and set each element to sub-class I can call sub-class overridden functions from the array. The new and delete keywords may also be necessary. \$\endgroup\$ Commented Mar 11, 2019 at 15:23
1
\$\begingroup\$

In this case you want to use virtual functions on the base class like so:

class Entity // base class
{
  virtual void ai(Entity n){}
}

Even though this is just example code, I can see that it might cause problems because you are passing by value instead of by reference.

\$\endgroup\$
2
  • \$\begingroup\$ In this case, surely virtual void ai(Entity n) = 0; is appropriate? \$\endgroup\$ Commented Mar 11, 2019 at 13:51
  • \$\begingroup\$ I would consider that an implementation detail, whether to use a virtual or pure virtual function. This is a good option but the requirements aren't exacty clear. \$\endgroup\$
    – Jay
    Commented Mar 11, 2019 at 14:09

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .