Skip to content

Instantly share code, notes, and snippets.

@sfalexrog
Created October 3, 2016 17:16
Show Gist options
  • Save sfalexrog/140ac17d49037ec913587bedbbdb79b3 to your computer and use it in GitHub Desktop.
Save sfalexrog/140ac17d49037ec913587bedbbdb79b3 to your computer and use it in GitHub Desktop.
Пример перегрузки операторов
// Здесь будем демонстрировать, как реализовывать всякие полезные операторы для собственных типов данных
#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