#c
#c
Вопрос:
Я определил Vector2
класс и подумал, что было бы неплохо иметь некоторые предопределенные элементы, такие как нулевой вектор или вектор, указывающий вправо.
Я создал следующий метод для нулевого вектора:
static inline Vector2 ZERO() {return Vector2(0, 0);}
Можно ли сделать это таким образом, или есть какие-то более разумные / эффективные способы сделать это, например, инициализировать нулевой вектор как const и указывать только на него?
Комментарии:
1. Вы должны обязательно объявить
ZERO
как const (какой смысл его менять?). В остальном все выглядит нормально.2. Если они действительно дешевы в создании, вам может просто понадобиться
zero()
фабричный метод или конструктор по умолчанию, который равен нулю.3. Являются ли эти векторы изменяемыми или неизменяемыми?
Ответ №1:
Я думаю, что это хороший способ. Но конструктор vector2 определен, нет необходимости использовать статическую функцию. Vector2 vZero = Vector2::ZERO(); // сложный, Vector2 vZero(0,0); // более простой.
Если вы хотите более легко,
Vector2{
public:
static const Vector2 ZEROVECTOR = Vector2(0,0);
...}
Вы можете использовать if(vVector == Vector2::ZEROVECTOR) ;// только один пустой вектор для каждого класса vector2 .
Ответ №2:
Еще одна идея:
Вы можете определить enum
для специального инициализатора, чтобы охватить некоторые из распространенных экземпляров.
Для этого не требуются сохраненные константы и только один дополнительный конструктор.
Пример:
#include <iostream>
// initializers for common things
enum Init {
Init0, // init a 0-vector
InitX, // init an x unit vector
InitY // init a y unit vector
};
struct Vector2 {
double x, y;
Vector2(Init init = Init0):
x(init == InitX), y(init == InitY)
{ }
Vector2(double x, double y): x(x), y(y) { }
};
std::ostreamamp; operator<<(std::ostream amp;out, const Vector2 amp;v)
{
return out << v.x << ", " << v.y;
}
#define DEBUG(...) std::cout << #__VA_ARGS__ << ";n"; __VA_ARGS__
int main()
{
DEBUG(Vector2 v0);
DEBUG(std::cout << v0 << 'n');
DEBUG(Vector2 v1(Init0));
DEBUG(std::cout << v1 << 'n');
DEBUG(Vector2 v2(InitX));
DEBUG(std::cout << v2 << 'n');
DEBUG(Vector2 v3(InitY));
DEBUG(std::cout << v3 << 'n');
DEBUG(Vector2 v4(1.0, 2.0));
DEBUG(std::cout << v4 << 'n');
}
Вывод:
Vector2 v0;
std::cout << v0 << 'n';
0, 0
Vector2 v1(Init0);
std::cout << v1 << 'n';
0, 0
Vector2 v2(InitX);
std::cout << v2 << 'n';
1, 0
Vector2 v3(InitY);
std::cout << v3 << 'n';
0, 1
Vector2 v4(1.0, 2.0);
std::cout << v4 << 'n';
1, 2
Пожалуйста, обратите внимание, что я этого Vector2::Vector2(Init)
не explicit
сделал.
Обычно я предпочитаю создавать конструкторы только с одним аргументом explicit
, чтобы предотвратить случайные преобразования (там, где я их не ожидаю). В этом случае я бы предпочел, чтобы InitX
его можно было использовать непосредственно там, где Vector2
ожидается (запуск неявного преобразования). Это делает эту функцию еще более удобной. (Я должен признать, что я назвал его, например XAxis
, вместо InitX
того, чтобы в моем реальном коде.)