Created
October 3, 2016 17:16
-
-
Save sfalexrog/140ac17d49037ec913587bedbbdb79b3 to your computer and use it in GitHub Desktop.
Пример перегрузки операторов
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Здесь будем демонстрировать, как реализовывать всякие полезные операторы для собственных типов данных | |
#include <iostream> | |
#include <cinttypes> | |
#include <cmath> | |
using namespace std; | |
// Объявляем собственный тип данных - вектор, содержащий две координаты. Координаты в данном случае будут | |
// целочисленными, типа int64_t (он же long long int) - 64-битное целое. | |
// Объявление собственного составного типа происходит так: сначала мы пишем ключевое слово struct, | |
// затем пишем название этого типа (в данном случае - ivec2 - "integral vector of size 2") | |
struct ivec2 | |
{ | |
int64_t x; | |
int64_t y; | |
// Здесь же можно указать те или иные методы, которые будут у типа данных. По сути, это будет та же | |
// функция, но ей неявно передаётся один параметр - собственно объект, над которым происходит операция. | |
// Это не дополнительное поле структуры - в нём ничего не содержится. | |
// В качестве примера используется вычисление квадрата модуля вектора (можно было и через скалярное произведение делать) | |
int64_t abs2() { return x * x + y * y; } // У метода есть доступ к полям структуры, сама структура передаётся неявно | |
} | |
// Операторы можно перегружать как внутри описания типа, так и вне его. Оператор, по своей сути, будет просто | |
// функцией, которая просто хитрым образом записывается и хитрым образом вызывается. | |
// Вот, например, переопределение суммы векторов. Результат - вектор, операнды - векторы. | |
// Следует всегда писать именно const ivec2&, а не просто ivec2 - во-первых, компилятор ожидает, что | |
// операнды (то, что слева и справа от знака "+") в результате сложения не будут изменены, во-вторых, | |
// амперсанд после имени означает, что передаём мы не копию объекта, а ссылку на него - так работает быстрее. | |
ivec2 operator+ (const ivec2& a, const ivec2& b) | |
{ | |
return {a.x + b.x, a.y + b.y}; // Результатом является новый вектор, его компоненты - a.x + b.x и a.y + b.y | |
} | |
// Аналогично реализуем разность векторов | |
ivec2 operator- (const ivec2& a, const ivec2& b) | |
{ | |
return {a.x - b.x, a.y - b.y}; | |
} | |
// Умножение на число - результатом опять будет вектор | |
ivec2 operator* (const int64_t coeff, const ivec2& v) | |
{ | |
return {coeff * v.x, coeff * v.y}; | |
} | |
// Скалярное произведение векторов - результатом будет число | |
int64_t operator% (const ivec2& a, const ivec2& b) | |
{ | |
return a.x * b.x + a.y * b.y; | |
} | |
// Векторное произведение для наших целей лучше тоже представлять как число | |
// Стоит заметить, что мы опять напишем operator*, но так как аргументы будут другими, | |
// компилятор поймёт, что это две разные функции. | |
int64_t operator* (const ivec2& a, const ivec2& b) | |
{ | |
return a.x * b.y - a.y * b.x; | |
} | |
// В качестве примера использования описанных выше операторов можно написать функцию, | |
// которая будет по заданным точкам - векторам - строить уравнение прямой. | |
void print_line_equation(const ivec2& p1, const ivec2& p2) | |
{ | |
int64_t A, B, C; | |
A = p1.y - p2.y; | |
B = p2.x - p1.x; | |
C = p1 * p2; | |
cout << A << " " << B << " " << C << endl; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment