Перегрузка операторов
Практика
Заголовок раздела «Практика»Реализуйте тип для Vector2 с 2-мя float полями в отдельном модуле (Vector2.h, по надобности Vector2.cpp).
Vector2 должен быть обычной структурой с публичными полями.
Перегрузите операторы (v, w это векторы, а a - float):
v * aa * v(то же, чтоv * a)v *= av / av /= av + wv - wv += w(c поддержкой синтаксиса(v += w) += w)v -= w- Чтобы
std::cout << vпечатал компонентыvчерез запятую, в скобках v[i]для получения ссылки на компонент (i равен 0 или 1).
- Перегрузите их как свободные
inline, внутриVector2.h; - В
Vector2.hоставьте только объявления перегруженных операторов, определения задайте вcppфайле; - Используйте вместо свободных функций методы, объявленные внутри класса, определенные в
cppфайле (там, где это возможно). Постарайтесь изменить прототипы и тела функций текстуальной заменой в вашем текстовом редакторе (search-and-replace).
В main.cpp протестируйте функционал через assert-ы.
Ключевые идеи
Заголовок раздела «Ключевые идеи»-
Почему оператор
v * wэто плохая идея?Ответ
Потому что есть скалярное произведение (dot product), а есть перемножение компонентов (hadamard product). Не очевидно, какую из этих операций выполнит
v * w. -
Как вызвать тот или иной оператор как функцию?
-
Что такое “fluent interface”? Как добавить его поддержку к операторам
<<,+=,-=и т.п.?Заметка
Fluent interface можно делать и без перегрузки операторов. Можно через методы тоже.
Со своим типом
Vector2, например, могли бы сделать так:struct Vector2{// ...public:Vector2& add(Vector2 v){*this = *this + v;return *this;}Vector2& sub(Vector2 v){*this = *this - v;return *this;}Vector2& scale(float a){*this = *this * a;return *this;}Vector2& printInto(std::ostream& out){// ...return *this;}};void usage(){Vector2 val{1, 2};val.add({ 1, 2 }).sub({ 2, 3 }).printInto(std::cout) // (0, 1).scale(5).add({ 1, 2 }).printInto(std::cout); // (1, 7)val.printInto(std::cout); // (1, 7)}Например, с печатью, дизайнеры языка могли бы сделать подобный интерфейс, вместо
<<:std::cout.print(v).print(std::endl).print(w).print(std::endl);Тут только минус в том, что нельзя было бы перегрузить
printпод свой тип, не имея дополнительного механизма перегрузки, как, например, метод внутриVector2с определенным именем, ожидаемым методомprint(printнадо вызвать перегруженную логику, используя, например, статический полиморизм черезtemplate).