Разыменованный указатель на элемент вектора в объекте не обновляет значение

Я пытаюсь создать игрушечную систему компонентов Entity, чтобы улучшить свои навыки C++. Для этого у меня есть класс ECS_Manager, который использует шаблоны, чтобы иметь несколько классов хранения для каждого типа данных, который я хотел бы использовать в качестве компонента.

Каждый компонент представляет собой просто структуру с целым числом и любыми другими данными, которые мне нужны. В примере он содержит объект Vector2D. Ничего особенного.

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

#include <iostream>
#include <vector>
#include <map>
#include <typeinfo>
#include <memory>
#include <array>

#include "Vector2D.hpp"
#include "./ECS/components/Position_comp.hpp"


class VComponentStorage {
  
  public:
      virtual ~VComponentStorage() = default;
};

template <typename T>
class ComponentStorage : public VComponentStorage{
    
  public:

    ComponentStorage(){
        this->storage_container_index = 0;
    }

    void add_component(T component){
    
        this->storage_container.push_back(component);
        this->storage_container_index++;
    
    }

    T *get_component(int entity_id){

        T* start_ptr = this->storage_container.data();
        
        return &(start_ptr[entity_id]); 
    }

    size_t get_component_count(){
        return 1;    
    }
  
  private:
      std::vector<T> storage_container;
      size_t storage_container_index;
};

class ECS_Mananger{

  public:
    
    ECS_Mananger(){

    }
    
    template<typename T> void register_component(){
        const char *type_name = typeid(T).name();
        
        ComponentStorage<T> *comp_storage_ptr = new ComponentStorage<T>;

        this->T_to_comp_storage_Map.insert({type_name, comp_storage_ptr});
        
    }
    
    template<typename T>
    void add_component(T component){
        const char *type_name = typeid(T).name();
        
        std::cout << type_name << std::endl;
        ComponentStorage<T>* my_ptr = static_cast<ComponentStorage<T>*>(this->T_to_comp_storage_Map[type_name]);
        my_ptr->add_component(component);
    }

    template<typename T>
    T *get_component(int entity_id){
        const char *type_name = typeid(T).name();

        ComponentStorage<T>* my_ptr = static_cast<ComponentStorage<T>*>(this->T_to_comp_storage_Map[type_name]);
        return my_ptr->get_component(entity_id);
    }

  private:

    std::map<std::string, VComponentStorage*> T_to_comp_storage_Map;
    

};

void Physics_System(ECS_Mananger &world){

    Position_Component* my_ptr = world.get_component<Position_Component>(0);
    *my_ptr = { 0, Vector2D(5.0, 2.0)};

};
int main() {
    
    //Create Arrays
   
    ECS_Mananger my_world;

    my_world.register_component<Position_Component>();
    
    Position_Component init_pos_val = {0, Vector2D(1.0, 2.0)};

    my_world.add_component<Position_Component>(init_pos_val);
    // Main game loop
    while (1) // Detect window close button or ESC key
    {
        // Update
        Physics_System(my_world); 
        my_world.get_component<Position_Component>(0)->position.print();
    }

    return 0;
}

В функции Physics_System я ожидаю, что значение будет обновлено. Любая причина, почему это не так? Мой C++ немного ржавый. Сначала я делал так: 'world.get_component<Position_Component>(0)->position = Vector2D(4.4, 3.3);' чтобы изменить значение. Это тоже не работало, поэтому я подумал, что, возможно, это как-то связано с правыми/левыми проблемами с языком. Я подозреваю, что хоть я и использую указатели, где-то что-то копируется. Я просто не могу сказать, где.

Редактировать:

Position_Component и спецификация Vector2D:

#include "Vector2D.hpp"

struct Position_Component {
    
    int entity_id;

    Vector2D position;

};
class Vector2D {
  public:
    double x;
    double y;


    Vector2D() {
        this->x = 0.0;
        this->y = 0.0;
    }

    Vector2D(double x, double y){
        this->x = x;
        this->y = y;
    }

    void print(){ std::cout << "(" << this->x << "," << this->y << ")" << std::endl; };


    Vector2D operator+(const Vector2D& vec){
        Vector2D result;
        result.x = this->x + vec.x;
        result.y = this->y + vec.y;
        
        return result;
    }

    Vector2D operator-(const Vector2D& vec){
        Vector2D result;
        result.x = this->x - vec.x;
        result.y = this->y - vec.y;

        return result;
    }

    Vector2D operator=(const Vector2D& vec){
        Vector2D result;
        result.x = vec.x;
        result.y = vec.y;
        return result;
    }
};


Vector2D operator*(const double& s, Vector2D vec){
        Vector2D result;
        result.x = s*vec.x;
        result.y = s*vec.y;
        
        return result;
}

ОТ: Функцию ComponentStorage<T>::get_component() можно было бы сократить до return &storage_container[entity_id];

Some programmer dude 30.03.2023 05:32

Что касается вашей проблемы, вы пытались отладить свою программу? Например, используя отладчик для пошагового выполнения кода, отслеживая переменные и их значения, чтобы увидеть, что происходит на самом деле?

Some programmer dude 30.03.2023 05:47

Как выглядит Position_Component?

kiner_shah 30.03.2023 08:05

@Someprogrammerdude У меня есть. Указатель, используемый в ECS_Manager (хранящийся в карте), используемый для ссылки на правильный объект ComponentStorage, содержит тот же адрес, когда компонент впервые регистрируется, добавляется и когда вызывается get_component. Я предполагаю, что когда я «запрашиваю» адрес PositionComponent, я получаю копию вектора (или элемента). Я просто не понимаю «почему».

user3047023 30.03.2023 17:04

@kiner_shah Вопрос отредактирован, чтобы включить Position_Component и содержащийся в нем класс Vector2D.

user3047023 30.03.2023 17:05
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
5
126
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема в вашем операторе присваивания Vector2D:

Vector2D operator=(const Vector2D& vec){
    Vector2D result;
    result.x = vec.x;
    result.y = vec.y;
    return result;
}

Предполагается, что оператор присваивания присваивает объекту this, а не создает новый объект. Он также должен возвращать ссылку на *this (чтобы разрешить цепочку присваиваний).

Из-за этой проблемы назначение

*my_ptr = { 0, Vector2D(5.0, 2.0)};

просто выбрасывается, вы никогда не изменяете *my_ptr.

Чтобы решить эту проблему, измените, например:

Vector2D& operator=(const Vector2D& vec){
    x = vec.x;
    y = vec.y;
    return *this;
}

Я рекомендую потратить некоторое время на чтение этого канонического справочника по реализации для перегрузки операторов.

Другие вопросы по теме