Как трактовать производный тип как его базовый тип? - PullRequest
2 голосов
/ 30 июня 2019

Мне интересно, можно ли трактовать класс как его базовый тип?Я сделал небольшой пример ниже, описывающий ситуацию, которую я имею в виду.
Я использую класс Vector2, который я пропустил в этом примере, но он просто состоит из значений x и y типаfloat.
Я пытаюсь заставить метод с именем FindEntitiesWithPosition работать с классами Person и Vechicle, но получаю ошибку E0312 no suitable user-defiend conversion from "std::vector<Person, std::allocator<Person>>" to "const std::vector<Entity, std::allocator<Entity>>" exists.Как я могу заставить этот код работать?

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));
}

Ответы [ 2 ]

4 голосов
/ 30 июня 2019

Вы можете рассматривать объект производного класса как объект базового класса.Как?Вы можете преобразовать указатель или ссылку на объект производного класса в указатель или ссылку на объект базового класса и продолжить работу с преобразованным указателем или ссылкой.Это преобразование является неявным, поэтому оно представляет собой плавный переход от (одного) производного объекта к его базовому объекту.Это также работает с умными указателями.

Вот момент, когда вещи перестают быть хорошими.Вы не можете рассматривать вектор (список, набор, вектор векторов, группу, что угодно) объектов производного класса как вектор (список, набор, вектор векторов, группу, что угодно) объектовБазовый класс.Сообщение об ошибке говорит вам только об этом.

4 голосов
/ 30 июня 2019

template соответствует вашим требованиям.
Я бы предложил что-то вроде этого.

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;
}

Кстати, следите за ненужными копиями при прохождении entities и в цикле Range-For.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...