Проблема проектирования классов C ++. Связывание класса с другими классами и количеством - PullRequest
0 голосов
/ 19 июня 2020

У меня есть следующие классы материалов, которые будут использоваться классом BlockTest. Сам класс Material никогда не будет использоваться и служит только для предоставления интерфейса для реализации всеми дочерними классами. Следовательно, класс Material потенциально может быть абстрактным классом.

class Material {
public:
    Material() : m_nQuantity(0) {}
    Material(uint8_t amount) : m_nQuantity(amount) {}
    virtual ~Material() {}

    virtual Vector2D* getTextureTop() {
        static Vector2D vector(0.0f, 0.0f);
        return &vector;
    }

    virtual uint16_t getMaterialId() {
        return 0;
    }

    uint8_t getQuantity() {
        return m_nQuantity;
    }

    uint8_t m_nQuantity;
};

class GrassMaterial : public Material {
public:
    GrassMaterial () : m_nQuantity(0) {}
    GrassMaterial (uint8_t amount) : Material(amount) {}
    virtual ~GrassMaterial () {}

    virtual Vector2D* getTextureTop() {
        static Vector2D vector(0.5f, 0.5f);
        return &vector;
    }

    virtual uint16_t getMaterialId() {
        return GRASS_BLOCK_ID;
    }

    uint8_t getQuantity() {
        return m_nQuantity;
    }
};

Класс Block должен иметь ссылку на до 4 различных дочерних классов Material, которые будут разными для каждого экземпляра класса Block.

class BlockTest {
public:

    void render() {
        std::cout << "BlockTest(Material&& m1, Material&& m2)" << std::endl;
        std::cout << m_m[0].getTextureTop()->m_x << ":" << m_m[0].getTextureTop()->m_y << std::endl;
        std::cout << (int)m_m[0].getQuantity() << std::endl;

        std::cout << m_m[1].getTextureTop()->m_x << ":" << m_m[1].getTextureTop()->m_y << std::endl;
        std::cout << (int)m_m[1].getQuantity() << std::endl;
    }

    BlockTest() {}
    BlockTest(const BlockTest &obj) = delete;
    ~BlockTest() {
        m_m[0].m_nQuantity = 255;
        m_m[1].m_nQuantity = 255;
    }

    Material m_m[4];
};

Использование:

BlockTest* bt = new BlockTest();
Material* m1 = new (&(b1->m_m[0])) GrassMaterial(54);
Material* m2 = new (&(b1->m_m[0])) StoneMaterial(84);

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

Производительность имеет решающее значение, поскольку я могу создавать ~ 840 миллионов объектов BlockTest в течение примерно 10 секунд, поэтому я не могу просто иметь массив Material * для каждого класса и конструирование каждого материала с помощью оператора new.

Объекты BlockTest имеют память, предварительно выделенную фрагментами по 65 536, а затем конструируются с использованием оператора размещения new для минимизации затрат на выделение кучи, и это не вызывает никаких проблем с производительностью. .

Что мне действительно нужно

Дочерние классы Материала определяют постоянные данные, которые различаются для каждого типа Материала (по сути, UV-карты текстуры, MATERIAL_ID, и т. д. c), поэтому эти переменные могут быть c статичными и просто доступны с помощью методов stati c без необходимости создавать экземпляр без дополнительных затрат памяти. Однако для каждого класса BlockTest также необходимо связать каждый дочерний класс Material, из которого он состоит (от 1 до 4 различных материалов), с количеством.

Например: BlockTest * b1 состоит из 3 материалов.

  • GrassMaterial в количестве 50.
  • StoneMaterial в количестве 155.
  • IronMaterial в количестве 50.

BlockTest * b2 состоит из 2 материалов.

  • GrassMaterial с количеством 90.
  • SandMaterial с количеством 165.

Для каждого экземпляра BlockTest это потребуется доступ к методам stati c каждого содержащегося в нем Материала (методы всегда одинаковы и определены в базовом классе материала), и ему потребуется способ связать каждый из этих материалов с его количеством.

I Представьте, что шаблоны могут быть лучшим способом приблизиться к этому, однако я не уверен, как подойти к связыванию каждого класса шаблона с количеством. Также, если класс BlockTest является шаблоном, мне нужен способ хранения массива объектов BlockTest * со всеми различными аргументами шаблона.

...