Reputation: 123
I'm wondering if it's possible to treat a class as its base type. I've made a small example below describing the situation i mean.
I use a Vector2
class that I've left out in the example, but it just consists of an x
and y
value of type float
.
I'm trying to make the method called FindEntitiesWithPosition
to work with the classes Person
and Vechicle
, but I get error E0312 no suitable user-defiend conversion from "std::vector<Person, std::allocator<Person>>" to "const std::vector<Entity, std::allocator<Entity>>" exists
. How can I make this code work?
class Entity {
public:
Entity (Vector2 position)
: position(position) { }
Vector2 position;
}
class Person : public Entity {
public:
Person(Vector2 position, std::string name)
: Entity(position), name(name) { }
std::string name;
}
class Vehicle : public Entity {
public:
Vehicle (Vector2 position, int power)
: Entity(position), power(power) { }
int power;
}
std::vector<Entity> FindEntitiesAtPosition(std::vector<Entity> entities, Vector2 position) {
std::vector<Entity> result;
for (Entity e : entities) {
if (e.position == position)
result.push_back(e);
}
return result;
}
int main() {
std::vector<Person> persons;
persons.emplace_back(Vector2(1.f, 1.f), "Alice");
persons.emplace_back(Vector2(2.f, 2.f), "Bob");
std::vector<Vehicle> vehicles;
persons.emplace_back(Vector2(1.f, 1.f), 3);
persons.emplace_back(Vector2(2.f, 2.f), 4);
// Should return person with name "Bob"
std::vector<Person> v1 = FindEntitiesAtPosition(persons, Vector2(2.f, 2.f));
// Should return vehicle with power 4
std::vector<Vehicle> v2 = FindEntitiesAtPosition(vehicles, Vector2(2.f, 2.f));
}
Upvotes: 2
Views: 434
Reputation: 119877
You can treat an object of a derived class as an object of a base class. How? You can convert a pointer or a reference to an object of a derived class to a pointer or a reference to an object of a base class, and continue working with the converted pointer or reference. This conversion is implicit so it is a seamless transition from a (single) derived object to its base object. It also works with smart pointers.
Here's the point where things stop being nice. You cannot treat a vector (list, set, vector of vectors, bunch, whatever) of objects of a derived class as a vector (list, set, vector of vectors, bunch, whatever) of objects of a base class. The error message is telling you just that.
Upvotes: 4
Reputation: 16850
template
matches your requirements.
I would suggest something like this.
template<typename T>
std::vector<T>
FindEntitiesAtPosition(const std::vector<T> &entities,
Vector2 position)
{
std::vector<T> result;
for(const auto &e: entities)
{
if(e.position == position)
{
result.emplace_back(e);
}
}
return result;
}
By the way, watch out the unneeded copies when passing entities
and in the range-for loop.
Upvotes: 4