Расположение полей класса в памяти
Имеется вот такой класс:
template <typename Type>
class Vector
{
public:
Type x, y, z;
};
Для удобства я добавил в него оперетор досутпа по индексу. Реализовал так:
template <typename Type>
class Vector
{
public:
Type& operator[] (size_t index)
{
switch (index)
{
case 0: return x;
case 1: return y;
case 2: return z;
}
return z;
}
public:
Type x, y, z;
};
Получилось громоздко. Позже мне пришло в голову написать такую версию оперетора:
template <typename Type>
Type& Vector<Type>::operator[] (size_t index)
{
return reinterpret_cast<Type*>(this)[index];
}
Будет ли последняя версия опрератора на разных платформах работать одинаково? При условии что:
- Тип у всех полей класса одинаковый.
- У всех полей одинаковый модификатор доступа.
Ответы (2 шт):
Если изменить интерфейс, можно обойтись без сомнительных приведений. Вы готовы писать v.x() = 42; ?
template <typename Type>
class Vector {
public:
Type& operator[](int i) {
return data[i];
}
Type& x() { return data[0]; }
Type& y() { return data[1]; }
Type& z() { return data[2]; }
private:
Type data[3];
};
Нет, гарантий таких нет и быть не может. Особенно если вдруг вы добавите в класс что-то виртуальное - это практически 100% гарантия, что адрес this и адрес первого поля будут разными.
Могут сыграть свою роль всякие выравнивания и тому подобные тонкости.
Но какой смысл обращаться к набору данных как к элементам массива, но при этом не сделать его массивом? Если животное на 4 лапах, лает, как собака, и кусается как собака - то это таки собака! Делайте массив.
Только в отличие от Stanislav Volodarskiy я бы - если вам дорого как память обращение через поля x, y, z - делал через ссылки:
template <typename Type>
class Vector {
public:
Type& operator[](int i) { return data[i]; }
const Type& operator[](int i) const { return data[i]; }
public:
Type &x = data[0], &y = data[1], &z = data[2];
private:
Type data[3];
};
Тогда обращение к данным ничем не отличается от вашего: https://ideone.com/W0y5M5