\documentclass{article}
\usepackage[utf8x]{inputenc}
\usepackage{ucs}
\usepackage{amsmath} 
\usepackage{amsfonts}
\usepackage{marvosym}
\usepackage{wasysym}
\usepackage{upgreek}
\usepackage[english,russian]{babel}
\usepackage{graphicx}
\usepackage{float}
\usepackage{textcomp}
\usepackage{hyperref}
\usepackage{geometry}
  \geometry{left=2cm}
  \geometry{right=1.5cm}
  \geometry{top=1cm}
  \geometry{bottom=2cm}
\usepackage{tikz}
\usepackage{ccaption}
\usepackage{multicol}
\usepackage{fancyvrb}

\usepackage{listings}
%\setlength{\columnsep}{1.5cm}
%\setlength{\columnseprule}{0.2pt}

\usepackage{colortbl,graphicx,tikz}
\definecolor{X}{rgb}{.5,.5,.5}

\title{ДЗ. Работа с изображениями в формате \texttt{.ppm}}
\date{}
\begin{document}
\pagenumbering{gobble}

\lstset{
  language=C++,                % choose the language of the code
  basicstyle=\linespread{1.1}\ttfamily,
  columns=fixed,
  fontadjust=true,
  basewidth=0.5em,
  keywordstyle=\color{blue}\bfseries,
  commentstyle=\color{gray},
  stringstyle=\ttfamily\color{orange!50!black},
  showstringspaces=false,
  %numbers=false,                   % where to put the line-numbers
  numbersep=5pt,
  numberstyle=\tiny\color{black},
  numberfirstline=true,
  stepnumber=1,                   % the step between two line-numbers.        
  numbersep=10pt,                  % how far the line-numbers are from the code
  backgroundcolor=\color{white},  % choose the background color. You must add \usepackage{color}
  showstringspaces=false,         % underline spaces within strings
  captionpos=b,                   % sets the caption-position to bottom
  breaklines=true,                % sets automatic line breaking
  breakatwhitespace=true,         % sets if automatic breaks should only happen at whitespace
  xleftmargin=.2in,
  extendedchars=\true,
  keepspaces = true,
}
\lstset{literate=%
   *{0}{{{\color{red!20!violet}0}}}1
    {1}{{{\color{red!20!violet}1}}}1
    {2}{{{\color{red!20!violet}2}}}1
    {3}{{{\color{red!20!violet}3}}}1
    {4}{{{\color{red!20!violet}4}}}1
    {5}{{{\color{red!20!violet}5}}}1
    {6}{{{\color{red!20!violet}6}}}1
    {7}{{{\color{red!20!violet}7}}}1
    {8}{{{\color{red!20!violet}8}}}1
    {9}{{{\color{red!20!violet}9}}}1
    {~} {$\sim$}{1}
}


\title{Семинар \#2: Инкапсуляция. Классные задачи.\vspace{-5ex}}\date{}\maketitle
\section*{Инкапсуляция}
Инкапсуляция -- это размещение в классе/структуре данных и функций, которые с ними работают. Структуру с методами можно называть классом. Переменные класса называются полями, а функции класса -- методами.
\begin{multicols}{2}\setlength{\columnseprule}{0.4pt}
\textbf{Без инкапсуляции:}
\begin{lstlisting}
#include <cmath>
#include <iostream>

struct Point 
{
    float x, y;
};

float norm(const Point& p) 
{
    return std::sqrt(p.x*p.x + p.y*p.y);
}

void normalize(Point& p) 
{
    float pnorm = norm(p);
    p.x /= pnorm;
    p.y /= pnorm;
}

Point operator+(const Point& l, 
                        const Point& r) 
{
    Point result = {l.x + r.x, l.y + r.y};
    return result;
}

int main() 
{
    Point p = {1, 2};
    normalize(p);
    std::cout << p.x << " " 
              << p.y << std::endl;
}

\end{lstlisting}

\textbf{С инкапсуляцией:}
\begin{lstlisting}
#include <cmath>
#include <iostream>

struct Point 
{
    float x, y;

    float norm() const 
    {
        return stdsqrt(x*x + y*y);
    }

    void normalize() 
    {
        float pnorm = norm();
        x /= pnorm;
        y /= pnorm;
    }

    Point operator+(const Point& r) const 
    {
        Point result = {x + r.x, y + r.y};
        return result;
    }
};

int main() 
{
	Point p = {1, 2};
	p.normalize();
	std::cout << p.x << " " 
	          << p.y << std::endl;
}
\end{lstlisting}
\end{multicols}
Обратите внимание на следующие моменты:
\begin{itemize}
\item[--] Методы имеют прямой доступ к полям \texttt{x} и \texttt{y}. Передавать саму структуру(или ссылку на неё) в методах не нужно.
\item[--] Вызов метода класса осуществляется с помощью оператора \texttt{.}(точка).
\item[--] Спецификатор \texttt{const} после объявления метода (например, \texttt{float norm() const}) означает, что этот метод не будет менять поля.
Желательно указывать этот спецификатор для всех методов, которые не изменяют объект.
\item[--] При перегрузке бинарных операций объектом является левый аргумент, а параметром функции -- правый. Т.е. \texttt{p + q} превратится в \texttt{p.operator+(q)}.
\end{itemize}


\subsection*{Модификаторы доступа \texttt{public} и \texttt{private}}
Модификаторы доступа служат для ограничения доступа к полям и методам класса.
\begin{itemize}
\item[--] \texttt{public} -- поля и методы могут использоваться где угодно
\item[--] \texttt{private} -- поля и методы могут использовать только методы этого класса и друзья (особые функции и классы, объявленные с использованием ключевого слова \texttt{friend})
\end{itemize}

\subsection*{Конструкторы}
Конструктор -- это специальный метод, который вызывается автоматически при создании экземпляра класса.
\begin{lstlisting}
struct Point {
private:
    float x, y;
public:
    // Конструктор:
    Point(float ax, float ay) 
    {
        x = ax;
        y = ay;
    }
    // другие методы
};

int main() 
{
    // Если несколько разных синтаксов создания экземпляра класса с вызовом конструктора:
    Point a = Point(7, 3);
    Point b(7, 3);
    Point c = {7, 3};
    Point d {7, 3};
    // Все они делают одно и то же - создают переменную на стеке и вызывают конструктор
    // В современном C++ предпочтительным является способ d
}
\end{lstlisting}
Особым видом конструктора является конструктор копирования:
\begin{lstlisting}
Point(const Point& p)
\end{lstlisting}
Он используется для создание нового экземпляра класса по уже имеющемуся экземпляру.\\
\textbf{Задача 3:} Сделайте задание в файле \texttt{4point\_constructors.cpp}

\subsection*{Ключевое слово \texttt{this} и оператор присваивания}
Ключевое слово \texttt{this} - это указатель на экземпляр класса, который можно использовать в методах этого класса.\\
Оператор присваивания -- это просто перегруженный оператор \texttt{=}. Оператор присваивания должен вернуть ссылку на текущий объект, то есть \texttt{*this}.\\

Нужно различать оператор присваивания и вызов конструктора:
\begin{lstlisting}
Point a = Point(7, 3);  // Конструктор ( оператор присваивания не вызывается )
Point b = a;            // Конструктор копирования ( оператор присваивания не вызывается )
Point c;                // Конструктор по умолчанию
c = a;                  // Оператор присваивания
\end{lstlisting}
Оператор присваивания должен возвращать ссылку на левый аргумент.

\newpage
\section*{Создаём свой класс строки}
Строки в языке \texttt{C} представляют собой просто массивы с элементами типа \texttt{char}(однобайтовое число). Работать с такими строками не очень удобно. Нужно выделять и удалять необходимую память, следить за тем, чтобы строка помещалась в эту память на всём этапе выполнения программы, для работы со этими строками нужно использовать специальные функции из библиотеки \texttt{string.h}. Это всё может привести к ошибкам. В этом разделе мы создадим класс \texttt{String} -- класс строки, с которым удобнее и безопаснее работать, чем со строками в стиле \texttt{C}. Заготовка класса выглядит так (Это далеко не самая эффективная реализация строки, более правильная реализация создаётся в примерах кода):
\begin{lstlisting}
#include <cstdlib>

class String 
{
private:

    size_t size;
    char* data;
    
public:

    String(const char* str) 
    {
        size = 0;
        while (str[size])
            size++;
		
        data = (char*)malloc(sizeof(char) * (size + 1));
		
        for (int i = 0; str[i]; i++)
            data[i] = str[i];
        data[size] = '\0';
    }
	
    size_t getSize() const 
    {
        return size;
    }
    
    const char* cStr() const 
    {
        return data;
    }
};

int main() 
{
    String a = "Elephant";
}
\end{lstlisting}

Схематично это можно представить следующим образом:
\begin{center}
\includegraphics[scale=0.86]{../images/string_base.png}
\end{center}

\newpage
\subsection*{Деструктор}
В коде выше выделяется память для массива \texttt{data}. Эта память выделяется при вызове конструктора (то есть при создании объекта). Однако она нигде не освобождается. Освободить её вручную мы не можем, так как поле \texttt{data} является приватным и это бы противоречило принципу сокрытия данных. Эта память должна освобождаться автоматически при удалении объекта.
\begin{lstlisting}
~ String() 
{
    free(data);
}
\end{lstlisting}

\subsection*{Перегруженные операторы класса \texttt{String}}
\begin{itemize}
\item \textbf{Оператор сложения:} \texttt{String operator+(const String\& right) const} \\
Этот оператор должен создавать новый экземпляр, задавать его поля (в частности придётся выделить память под строку-сумму) и возвращать этот экземпляр.

\item \textbf{Оператор присваивания сложения:} \texttt{String\& operator+=(const String\& right)}\\
Этот оператор не должен создавать новый экземпляр. Он должен изменять левый операнд (т. е. сам объект), и возвращать ссылку на этот объект (т. е. \texttt{*this}).

\item \textbf{Оператор присваивания:} \texttt{String\& operator=(const String\& right)}\\
Этот оператор не должен создавать новый экземпляр. Он должен изменять левый операнд (т. е. сам объект), так чтобы он стал идентичен правому. Если размеры строк не совпадают, то в данной реализации строки вам придётся удалить память левой строки и снова выделить память нужного размера. При этом нужно отдельно рассмотреть случай когда левый и правый операнд это один и тот же объект. 
\begin{lstlisting}
String a {"Cat"};
a = a;
\end{lstlisting}
Конечно, в этом случае ничего удалять не нужно.

\item \textbf{Оператор сравнения:} \texttt{bool operator==(const String\& right) const}\\
Этот оператор должен сравнивать строки (массивы \texttt{data}) и возвращать \texttt{true} или \texttt{false}.

\item \textbf{Оператор индексации:} \texttt{char\& operator[](unsigned int i)}\\
Этот оператор должен возвращать ссылку на \texttt{i}-ый символ строки.

\item \textbf{Индексация с проверкой на выход за границы:} \texttt{char\& at(unsigned int i)}\\
Этот метод должен проверять, что индекс \texttt{i} не выходит за границы диапазона и, если это так, возвращать ссылку на \texttt{i}-ый символ строки. Иначе, этот метод должен печатать сообщение об ошибке и завершать программу.
\end{itemize}

\newpage
\section*{Раздельная компиляция класса}
Методы можно вынести из определения класса следующим образом:
\begin{multicols}{2}\setlength{\columnseprule}{0.4pt}
\textbf{Определение методов в теле класса:}
\begin{lstlisting}
#include <cmath>
#include <iostream>


struct Point 
{
    float x, y;

    float norm() const 
    {
        return std::sqrt(x *x + y * y);
    }

    void normalize() 
    {
        float pnorm = norm();
        x /= pnorm;
        y /= pnorm;
    }

    Point operator+(const Point& r) const 
    {
        Point result = {x + r.x, y + r.y};
        return result;
    }
};





int main()
{
	Point p = {1, 2};
	p.normalize();
	std::cout << p.x << " " 
              << p.y << std::endl;
}
\end{lstlisting}
\vfill\null
\columnbreak

\textbf{Определение методов вне тела класса:}
\begin{lstlisting}
#include <cmath>
#include <iostream>

struct Point 
{
    float x, y;

    float norm() const;
    void normalize();
    Point operator+(const Point& r) const;
};

float Point::norm() const 
{
    return sqrt(x*x + y*y);
}

void Point::normalize() 
{
    float pnorm = norm();
    x /= pnorm;
    y /= pnorm;
}

Point Point::operator+(const Point& r) const
{
    Point result = {x + r.x, y + r.y};
    return result;
}

int main() 
{
	Point p = {1, 2};
	p.normalize();
	std::cout << p.x << " " 
              << p.y << std::endl;
}
\end{lstlisting}
\end{multicols}

Теперь эти методы можно скомпилировать отдельно. Для этого их нужно вынести в отдельный компилируемый файл \texttt{point.cpp}, а определение класса в отдельный файл \texttt{point.h}. Так называемый заголовочный файл \texttt{point.h} нужен, так как определение класса нужно и файле \texttt{point.cpp} и в файле \texttt{main.cpp}. Для компиляции используем:
\begin{verbatim}
g++ main.cpp point.cpp
\end{verbatim}

\begin{center}
\includegraphics[scale=0.65]{../images/sepcompilation.png}
\end{center}

\end{document}