Можно ли усечь массив производных классов в массив базовых классов в C ++? - PullRequest
2 голосов
/ 07 февраля 2011

Я делаю приложение, которое использует OpenGL и в настоящее время хранит массив объектов, которые должны отображаться в каждом кадре, который выглядит примерно так:

class Object {
  private:
    float x;
    float y;
  public:
    void func1();
    void func2();
    ...
};

Я бы хотел иметь возможность создать объект буфера вершин из массива этих объектов, но я не могу просто передать массив, так как класс содержит дополнительные функции, которых glBufferData не ожидает.

Можно ли разделить класс объекта следующим образом:

class baseObject {
  public:
    float x;
    float y;
};

class derivedObject : public baseObject {
  public:
    float x;
    float y;
    void func1();
    void func2();
    ...
};

, а затем приведите массив derivedObjects в массив baseObjects, используя static_cast или иным образом, который затем может быть передан glBufferData? Или это единственный способ перебрать массив объектов, извлекая переменные x и y в отдельный массив, который затем может быть передан в glBufferData?

Ответы [ 4 ]

2 голосов
/ 07 февраля 2011

Функции в вашем классе Object на самом деле ничего не вносят в макет объекта. Хотя спецификация не гарантирует этого, во всех основных компиляторах представление объекта в памяти - это просто его поля. (Однако, если вы добавите виртуальную функцию в микс, это не так). В вашем случае ваш класс Object будет выглядеть неотличимым от этого struct в памяти:

struct JustObjectFields {
    float x, y;
};

Потому что, когда вы удаляете функции-члены, это то, что у вас остается.

Причина этого в том, что функции-члены обычно компилируются в обычные функции, которые принимают указатель this в качестве явного первого аргумента. Этот код отделен от любого экземпляра класса, и поэтому размер класса не зависит от них. Короче говоря, вы должны быть в состоянии сделать это без использования наследования вообще. Просто используйте ваш сырой Object класс.

0 голосов
/ 08 февраля 2011

Краткий ответ: да.Если glBufferData принимает baseObject в качестве параметра, тогда также может использоваться derivedObject, поскольку экземпляр класса derivedObject также является экземпляром класса baseObject.

Проблема здесь не в методах / функциях, а в данных.glBufferData ожидает экземпляр класса baseObject в качестве параметра, поскольку для метода требуется объект, содержащий в точности элементы данных, описанные в baseObject.Object недопустим в качестве параметра, поскольку его элементы данных могут отличаться от baseObject.Это может привести к катастрофическим последствиям, если методу передается объект с недопустимыми данными.

Однако, определяя derivedObject как наследуемое от baseObject, мы говорим, что derivedObject IS baseObject плюс все элементы данных, перечисленные в определении derivedObject.Поэтому, когда мы передаем экземпляр derivedObject в glBufferData, он может обрабатывать его как экземпляр baseObject без опасности.

0 голосов
/ 07 февраля 2011

Typecast для массивов в этом случае не работает - http://codepad.org/6DFLPPDH
В общем случае невозможно преобразовать массив производных объектов в массив базовых объектов без перемещения данных, и я думаю, никто не беспокоился специально поддерживать случай, когда производный класс добавляет только методы.
На самом деле, даже приведение указателя массива не очень надежно - http://codepad.org/15a4cCy9
Но с простыми указателями это, конечно, не проблема - http://codepad.org/4vEK5wY1
И в вашем случае все должно быть в порядке, я думаю.

0 голосов
/ 07 февраля 2011

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

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