C ++ Наследование и как передавать и поддерживать данные подкласса через суперкласс - PullRequest
2 голосов
/ 13 июля 2011

Хорошо, я не совсем знал, как сформулировать вопрос, и не смог найти дубликатов, которые, я думаю, действительно решают эту ситуацию.

По сути, у меня есть суперкласс, к которому добавляются дополнительные данные через подкласс. Класс контейнера для этих данных распознает только суперкласс и корректирует характеристики на основе параметра id в суперклассе.

До недавнего времени мне никогда не приходилось использовать наследование в c ++, так что извините, если это тривиально. У меня сложилось впечатление, что когда я копирую кучу данных с использованием суперкласса, данные подкласса, так сказать, теряются в переводе. Чтобы обойти это ограничение, я пытаюсь использовать указатель с типом, однако теперь у меня возникает ошибка сегментации при попытке освободить память даже при типизации параметра указателя в функции free ().

Вот пример кода ...

1009 * Структура *

// Super class
struct Vertex {
    __declspec(align(4)) unsigned int vType;              // Identifies the vertex type.

    Vertex(const unsigned int _vType) : vType(_vType) { }
    Vertex(const Vertex &_rV) : vType(_rV.vType) { }      // Copy constructor
    virtual ~Vertex() { }

    unsigned int GetVType() const { return vType; }
};

// Subclass
// Id = 1
struct V_Pos : Vertex {
    __declspec(align(4)) XMFLOAT3 position;

    V_Pos(void) : Vertex(1) { }
    V_Pos(XMFLOAT3 &_rPosition) : Vertex(1), position(_rPosition) { }
    V_Pos(const V_Pos &_rV) : Vertex(_rV), position(_rV.GetPosition()) { } // Copy constructor
    ~V_Pos() { }

    XMFLOAT3 GetPosition() const { return position; }
};

Вот как я сейчас копирую данные.

// pBuffer is declared as a Vertex* data type
pBuffer = new V_Pos[_bufSize];

if (_pVBuffer->GetVType() == 1)
    for (unsigned int i = 0; i < bufSize; ++i) {
        V_Pos *_temp = (V_Pos*)&_pVBuffer[i];
        pBuffer[i] = *_temp;
    }

Вот как я сейчас перераспределяю данные.

if (pBuffer != 0) {
    delete [] pBuffer;
    pBuffer = 0;
}

Каков правильный подход к этой ситуации?

Редактировать 1 -

Обновлены вышеприведенные блоки кода, чтобы прояснить обсуждение комментариев под ответом knulp.

Ответы [ 3 ]

2 голосов
/ 14 июля 2011

Если вы начнете смешивать низкоуровневое выделение памяти с объектами malloc () / free () и C ++, вы столкнетесь с множеством проблем, в то время как ваш код станет практически нечитаемым.

Вы должны создать новый объект с новым на соответствующем конструкторе, который автоматически 1) выделяет память и 2) инициализирует структуру.Чтобы правильно освободить память, вы должны использовать delete и деструктор.

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

Почему вы используете поле типа?C ++ имеет очень сильные возможности типизации, поэтому нет смысла обходить весь механизм C ++ для определения vType.Скорее, определите базовый класс и два или более производных класса оттуда и просто удалите поле vtype.

Если вы используете чистое программирование ОО, вы избежите всех этих проблем с самого начала.

1 голос
/ 13 июля 2011

Ваш базовый класс должен иметь виртуальный деструктор. Это позволит вам безопасно удалить производный класс с указателем базового класса.

0 голосов
/ 13 июля 2011

Не то! Используйте конструктор копирования.

    // Super class
struct Vertex {
    __declspec(align(4)) unsigned int vType; // Identifies the vertex type.
    Vertex(const unsigned int _vType) : vType(_vType) { }

    unsigned int GetVType() const { return vType; }

    Vertex(const Vertex& v) : vType(v.vType) {}
};

// Subclass
// Id = 1
struct V_Pos : Vertex {
    __declspec(align(4)) XMFLOAT3 position;

    V_Pos(void) : Vertex(1) { }
    V_Pos(XMFLOAT3 &_rPosition) : Vertex(1), position(_rPosition) { }

    V_Pos(const V_Pos& v) : Vertex(v) { 
       position[0] = v.position[0];
       position[1] = v.position[1];
       position[2] = v.position[2];
    }
};

Еще лучше, используйте vecotr вместо XMFLOAT3;

Создать копию в куче: V_Pos оригинал (...); V_Pos * copyPtr = новый V_Pos (оригинал);

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