0

I'm making a tower defense game by using c++ & sfml. I have the classes (object, Tower, Enemy), The classes Tower and Enemy inherite class object;

enter image description here

see this code:

int main()
{
    std::list<object*> Objects;

    .....

    while(window.isOpen())
    {
        .......

        for(auto a:Objects)
        {
            for(auto b:Objects)
            {
                if(a != b && a->name == "tower" && b->name == "enemy" && distance(a, b) <= a->range)
                {
                    a->targets.push_back(b); // here's the problem, when i compile it i get:
                }                            // error: 'class object' has no member named 'targets'
            }
        }
    }
}

My problem is:

class 'Tower' has member 'targets' which is 'list' and because 'Tower' inherite 'object' so i can add it's pointer to list 'objects', I can edit 'x, y, name' but i can't edit the members in 'Tower' as the compiler told (error: 'class object' has no member named 'targets').

What is the solution?

ali kamel
  • 33
  • 1
  • 4

2 Answers2

2

object a is of type object, so how does the compiler know it's a tower, even if you do?

You can cast the object to a object of type tower like this:

Tower* tower = dynamic_cast<Tower*>(a);
if (tower)
    tower->targets..

Just keep in mind - if the object you're casting wasn't actually of the type Tower, dynamic_cast will return nullptr.

To use dynamic_cast, your source type must be polymorphic - you can make the object class polymorphic easiest by adding a virtual destructor:

class object
{
    public:
    virtual ~object(){}
    ..
}
Alan Birtles
  • 32,622
  • 4
  • 31
  • 60
Bas in het Veld
  • 1,271
  • 10
  • 17
  • 2
    Note that regular need for dynamic casts generally indicates there is something wrong with your design – Alan Birtles Jan 18 '20 at 09:33
  • Care to elaborate @Klaus? Looks ok to me, they mention the need for a null pointer check – Alan Birtles Jan 18 '20 at 09:35
  • By running this, the only problem I encounter is that the object class is not polymorphic, but that's a compiler error, not a crash – Bas in het Veld Jan 18 '20 at 09:38
  • @AlanBirtles: If there is a code example given, why it is not extended with a simple `if`? Having only a remark somewhere in the text is nice, but can be simply ignored by fast readers. So simply improve quality by adding it. – Klaus Jan 18 '20 at 10:00
1

The issue is that you are trying to access the targets member of a Tower instance through a pointer to an object. The class object doesn't have a targets member, Tower has, hence the error message.

The solution is to cast a to a pointer to Tower with dynamic_cast, and after that you can use its targets member. To be able to use dynamic_cast your object class have to be polymorphic (for details see this). You can achieve that by defining atleast 1 virtual function in object. The easiest is to define a default destructor.

class object {
    virtual ~object() = default;

    // ...
}
if (auto tower = dynamic_cast<Tower*>(a)) {
    tower->targets.push_back(b);
} else {
    // 'a' is not a 'Tower'.
}
Doeus
  • 430
  • 1
  • 3
  • 7
  • I've just corrected my answer. `object` has to be polymorphic in order to be castable by `dynamic_cast`. If it worked for you that means you already have a `virtual` function in it, and defining a `virtual` destructor is unnecessary in that case. – Doeus Jan 18 '20 at 10:02