Как мне получить доступ к переменным подкласса в векторе базового класса? (для системы компонентов сущности) - PullRequest
0 голосов
/ 28 мая 2020

Итак, у меня есть вектор с «Компонентами». Я могу легко получить доступ к переменным компонента из вектора, но когда я добавляю подкласс к вектору, я не могу получить доступ к этим переменным.

Может быть, это действительно смелый вопрос, и решение, вероятно, действительно сложное, но я не знаю, с чего начать и что попробовать, поэтому любая помощь приветствуется.

struct Component {};
std::vector<Component> components;

struct Transform : Component
{
    int x, y;
};

void Start()
{
    components.push_back(Transform());
    //can't acces x below
    std::cout << components[0].x;
}

РЕШЕНИЕ

сделайте вектор только для уникальных указателей:

std::vector<std::unique_ptr<Component>> components;

шаг 2:

void Start()
{   
    //add component (pointer to vector)
    components.push_back(std::make_unique<Transform>());
    //cast to Transform
    Transform const* transform = static_cast<Transform*>(components[0].get());

    std::cout << transform->x;
}

Ответы [ 2 ]

1 голос
/ 28 мая 2020

Прежде всего, у вас проблема с нарезкой объектов, чтобы отсортировать их, вы можете сделать что-то вроде:

struct Component {};
std::vector<std::unique_ptr<Component>> components;

struct Transform : Component
{
   int x = 0, y = 0;
};

void Start()
{
    components.push_back(std::make_unique<Transform>());
}

Что касается доступа к членам Transform, у вас есть несколько вариантов. В C ++ встроен rtti, но имейте в виду, что он довольно медленный:

Transform const* transform = dynamic_cast<Transform*>(components[0].get());
if(transform != nullptr)
    std::cout << transform.x;

Другой вариант - реализовать виртуальную функцию из Component:

struct Component
{
    virtual void Update();
};

struct Transform : public Component
{
    int x = 0, y = 0;
    virtual void Update() override
    {
        std::cout << x;
    }
};

void Start()
{
    components.push_back(std::make_unique<Transform>());
    for(Component& component : components)
    {
        component.Update();
    }
}
1 голос
/ 28 мая 2020

Проблема в том, что ваш вектор хранит объекты класса Component. Что происходит в push_back, так это то, что вектор создает новый Component, который скопирован из вашего Transform() объекта.

Итак, первое, что нужно отметить здесь, это то, что вы на самом деле не поместили объект sh a Transform в вектор, поэтому такого .x.

не существует. Обратите внимание, что в C ++ просто строка Transform x{}; создает объект в стеке. Таким образом, Component y=x; создает другой объект и копирует его данные (которые в данном случае отсутствуют, поскольку Component пуст) из x.
И это, по сути, то, что происходит в вашем коде, только немного скрытое с помощью in вектор.

...