Дизайн классов: массивы против нескольких переменных
У меня немного теоретический вопрос, однако это проблема, с которой я иногда сталкиваюсь при разработке классов, и я вижу, что это делается по-другому, когда читаешь другие коды. Что из следующего было бы лучше и почему:
пример 1:
class Color
{
public:
Color(float, float, float);
~Color();
friend bool operator==(Color& lhs, Color& rhs);
void multiply(Color);
// ...
float get_r();
float get_g();
float get_b();
private:
float color_values[3];
}
Пример 2:
class Color
{
public:
// as above
private:
float r;
float g;
float b;
}
Есть ли общее правило, которое следует придерживаться в таких случаях, или это просто до программиста и что, по-видимому, имеет больше смысла?
Ответы
Ответ 1
Это зависит от того, собираетесь ли вы выполнять итерацию по всему массиву?
В этом случае я считаю, что решение 1 более подходит.
Очень полезно иметь такой массив, когда у вас есть функции, которые работают в цикле данных
например.
void BumpColors(float idx)
{
for (int i = 0; i < 3; ++i)
color_values[i] += idx;
}
против
void BumpColors(float idx)
{
color_values[0] += idx;
color_values[1] += idx;
color_values[2] += idx;
}
Конечно, это тривиально, и я думаю, что это действительно вопрос предпочтения. В некоторых редких случаях у вас могут быть API-интерфейсы, которые используют указатель на данные, хотя вы можете делать
awesomeAPI((float*)&r);
Я бы предпочел сделать
awesomeAPI((float*)&color_values[0]);
потому что массив гарантирует его смежность, тогда как вы можете испортить смежность, добавив по ошибке другую переменную-член, которая не связана после float r.
Производительность мудрых не будет никакой разницы.
Ответ 2
И
Используйте это:
class Color {
// ...
private:
union {
struct {
float r, g, b;
};
float c[3];
};
};
Тогда c[0]
будет эквивалентно r
и т.д.
Ответ 3
Я бы сказал, что второй лучший.
Во-первых, данные, которые содержат ваши переменные, не предполагается (физически) находиться в массиве. Если бы у вас был класс с 3 студентами, не более, не менее, вы бы поставили их в массив, потому что они представляют собой массив студентов, но здесь он просто раскрашивает.
Во-вторых, кто-то, кто читает ваш код, также может во втором случае быстро понять, что содержат ваши переменные (r - красный и т.д.). Это не относится к массиву.
В-третьих, у вас будет меньше ошибок, вам не нужно будет помнить "о, в моем массиве красный - 0, g - 1, b - 2", и вы не будете ошибочно заменяться
return color_values[0]
по
return color_values[1]
в вашем коде.
Ответ 4
Я думаю, что вы правы: "Это просто программист и, как представляется, имеет больше смысла". Если бы это была моя программа, я бы выбрал одну или другую форму, не беспокоясь об этом слишком много, а затем напишу некоторые другие части программы, а потом снова перейдем к вопросу.
Одним из преимуществ дизайна, ориентированного на класс, является то, что он делает внутренние детали реализации такого рода частными, что упрощает их позднее.
Я думаю, что ваш вопрос имеет значение, только я сомневаюсь, что он может ответить на него хорошо, пока не будет написано больше кода. В реферате есть только три элемента, а три имеют имена - красный, зеленый и синий - поэтому я думаю, что вы могли бы пойти в любом случае с этим. Если принудительно выбрать, я выбираю пример 2.
Ответ 5
Есть ли общее правило, которое следует придерживаться в таких случаях, или это просто до программиста и что, по-видимому, имеет больше смысла?
Это определенно зависит от программиста и имеет смысл.
В вашем случае второй вариант кажется более подходящим. В конце концов, логически думая, ваш член не является массивом значений, а значениями для r
, g
и b
.
Ответ 6
Преимущества использования массива:
- Поддержание работоспособности: вы можете использовать значения в массиве для цикла
- Поддержание работоспособности: когда нужно добавить значение (например, желтый?), чем вам не нужно менять много кода.
Неудобство:
- Читаемость: "значения" имеют более четкие имена (а именно, r, g, b в этом случае).
В вашем случае, вероятно, лучше всего использовать переменные r, g, b, так как маловероятно, что цвет добавляется, а цикл над 3 элементами, вероятно, имеет меньшее значение, чем читаемость.
Ответ 7
Иногда программист будет использовать массив (или структуру данных)
чтобы быстрее сохранить данные на диск (или память), используя 1 операцию записи.
Это особенно полезно, если вы читаете и записываете много данных.