seminar2
This commit is contained in:
parent
46d1c64684
commit
ab6732eded
98 changed files with 10319 additions and 0 deletions
Binary file not shown.
|
|
@ -0,0 +1,405 @@
|
||||||
|
\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}
|
||||||
34
seminar02_encapsulation/classroom_tasks/code/0book/00oop.cpp
Normal file
34
seminar02_encapsulation/classroom_tasks/code/0book/00oop.cpp
Normal file
|
|
@ -0,0 +1,34 @@
|
||||||
|
/*
|
||||||
|
Объектно-ориентированное программирование (ООП) основано на представлении программы в виде совокупности взаимодействующих объектов
|
||||||
|
|
||||||
|
Основные принципы ООП: абстракция, инкапсуляция, наследование и полиморфизм
|
||||||
|
|
||||||
|
|
||||||
|
Абстракция: использование только тех характеристик объекта, которые с достаточной точностью представляют его в данной системе.
|
||||||
|
|
||||||
|
В каком-то смысле обычные структуры из языка C являются примером абстракции
|
||||||
|
|
||||||
|
struct book
|
||||||
|
{
|
||||||
|
char title[100];
|
||||||
|
float price;
|
||||||
|
int pages;
|
||||||
|
};
|
||||||
|
|
||||||
|
Для описание книги в коде мы используем лишь некоторое её характеристики, достаточные для нашей задачи
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Инкапсуляция: связывание данных некоторого абстрактного объекта и функций для работы с ним
|
||||||
|
Тесно связано с инкапсуляцией такое понятие как сокрытие
|
||||||
|
|
||||||
|
Сокрытие: разделение данных и функций абстрактного объекта на открытые (видимые извне) и скрытые (видимые только внутри самого объекта)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Наследование и Полиморфизм будут пройдены позже в курсе
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main(){}
|
||||||
54
seminar02_encapsulation/classroom_tasks/code/0book/01book.c
Normal file
54
seminar02_encapsulation/classroom_tasks/code/0book/01book.c
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
Хоть язык C и не является объектно-ориентированным, некоторые зачатки подходов ООП в нём тоже есть
|
||||||
|
Например, структуры языка C являются примером Абстракции
|
||||||
|
|
||||||
|
Для работы со структурами мы обычно писали функции так, что каждая из этих функций принимает на вход первым аргументом указатель на наш объект.
|
||||||
|
Такой подход НЕ является примером Инкапсуляции, так как структура и функции для работы с ней являются независимыми друг от друга.
|
||||||
|
При желании или по ошибке можно первым аргументом в эти функции передать вообще объект другого типа.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Эта программа написана на языке C, для компиляции используйте gcc:
|
||||||
|
gcc 00book.c
|
||||||
|
|
||||||
|
Функции в этом примере делают следующее:
|
||||||
|
|
||||||
|
make_discount сделать скидку на книгу, но цена на книгу не может упасть ниже 0.
|
||||||
|
print_book напечатать информацию о книге на экран
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct book
|
||||||
|
{
|
||||||
|
char title[100];
|
||||||
|
float price;
|
||||||
|
int pages;
|
||||||
|
};
|
||||||
|
typedef struct book Book;
|
||||||
|
|
||||||
|
|
||||||
|
void make_discount(Book* pb, int discount)
|
||||||
|
{
|
||||||
|
if (pb->price > discount)
|
||||||
|
pb->price -= discount;
|
||||||
|
else
|
||||||
|
pb->price = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print_book(const Book* pb)
|
||||||
|
{
|
||||||
|
printf("%s, price = %.2f, pages = %i\n", pb->title, pb->price, pb->pages);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Book b = {"War and Peace", 1700, 900};
|
||||||
|
|
||||||
|
print_book(&b);
|
||||||
|
make_discount(&b, 500);
|
||||||
|
print_book(&b);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
Эта программа написана на языке C++, для компиляции используйте g++:
|
||||||
|
g++ 01book.cpp
|
||||||
|
|
||||||
|
В языке C++ появились ссылки, которые могут немного упростить код из предыдущего файла
|
||||||
|
|
||||||
|
Тем не менее, структура Book и функции для работы с ней всё ещё являются независимыми друг от друга.
|
||||||
|
То есть тут тоже нет Инкапсуляции.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
struct Book
|
||||||
|
{
|
||||||
|
char title[100];
|
||||||
|
float price;
|
||||||
|
int pages;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void makeDiscount(Book& b, int discount)
|
||||||
|
{
|
||||||
|
if (b.price > discount)
|
||||||
|
b.price -= discount;
|
||||||
|
else
|
||||||
|
b.price = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void printBook(const Book& b)
|
||||||
|
{
|
||||||
|
std::cout << b.title << ", price = " << b.price << ", pages = " << b.pages << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Book b = {"War and Peace", 1700, 900};
|
||||||
|
|
||||||
|
printBook(b);
|
||||||
|
makeDiscount(b, 500);
|
||||||
|
printBook(b);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
Инкапсуляция - это объединение данных и функций для работы с ними
|
||||||
|
|
||||||
|
Объекты-данные, составляющие наш объект, называются полями
|
||||||
|
Функции для работы с этими данными называются методами
|
||||||
|
То есть у структуры Book из этого примера есть 3 поля (title, price и pages) и 2 метода (makeDiscount и print)
|
||||||
|
|
||||||
|
|
||||||
|
Сравните код в этом файле с кодом из предыдущего файла и обратите внимание на следующие моменты:
|
||||||
|
|
||||||
|
1) Функции для работы со структурой сейчас объявляются внутри структуры.
|
||||||
|
Получается методы как-бы принадлежат самой структуре
|
||||||
|
Это делает невозможным использование этих функций (случайно или намерено) для работы с объектами других типов.
|
||||||
|
|
||||||
|
2) Вызов методов осуществляется с помощью точки, то есть такой вызов из прошлого файла:
|
||||||
|
makeDiscount(b, 500);
|
||||||
|
заменился на такой:
|
||||||
|
b.makeDiscount(500);
|
||||||
|
|
||||||
|
То есть объект как бы сам вызывает функцию для работы со своими данными, а не передаётся первым аргументом в функцию.
|
||||||
|
|
||||||
|
|
||||||
|
3) Методы "знают" о том объекте, который их вызвал
|
||||||
|
|
||||||
|
Например, в методе makeDiscount используется поле price без указания объекта, которому принадлежит это поле
|
||||||
|
Но метод сам "знает" какой объект его вызвал, поэтому если его вызывает объект a вот так:
|
||||||
|
a.makeDiscount(500);
|
||||||
|
то в этом случае метод использует поле price объекта a
|
||||||
|
|
||||||
|
|
||||||
|
4) Константный метод не меняет полей вызывающего объекта.
|
||||||
|
Чтобы указать, что метод является константным нужно написать const в конце объявления метода
|
||||||
|
|
||||||
|
В предыдущем файле при передаче по константной ссылке передаваемый объект не мог измениться внутри функции
|
||||||
|
void printBook(const Book& b) -> printBook(b) не изменит b
|
||||||
|
|
||||||
|
Аналог этого для константного метода:
|
||||||
|
void print() const -> b.print() не изменит b
|
||||||
|
Следовательно, внутри константного метода нельзя менять поля объекта
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
struct Book
|
||||||
|
{
|
||||||
|
char title[100];
|
||||||
|
float price;
|
||||||
|
int pages;
|
||||||
|
|
||||||
|
void makeDiscount(int discount)
|
||||||
|
{
|
||||||
|
if (price > discount)
|
||||||
|
price -= discount;
|
||||||
|
else
|
||||||
|
price = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print() const
|
||||||
|
{
|
||||||
|
std::cout << title << ", price = " << price << ", pages = " << pages << std::endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Book a = {"War and Peace", 1700, 900};
|
||||||
|
Book b = {"The Master and Margarita", 600, 400};
|
||||||
|
|
||||||
|
a.print();
|
||||||
|
a.makeDiscount(500);
|
||||||
|
a.print();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Напечатайте книгу b
|
||||||
|
|
||||||
|
2) Сделайте скидку для книги b в 1000 рублей и напечатайте её ещё раз
|
||||||
|
|
||||||
|
3) Напишите метод void setPrice(float newPrice) который будет задавать новую цену книги
|
||||||
|
Вызовите этот метод для книги b и установите её цену в 1000 рублей. Напечатайте книгу ещё раз.
|
||||||
|
|
||||||
|
4) Попробуйте изменить поле внутри константного метода print, к какой ошибке это приведёт?
|
||||||
|
|
||||||
|
5) Можно ли вызвать метод makeDiscount из константного метода?
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
Задачи: Представлена структура Movie, описывающая фильм на Кинопоиске
|
||||||
|
title - название фильма
|
||||||
|
releaseYear - год выхода
|
||||||
|
numVotes - число оценок этого фильма на Кинопоиске
|
||||||
|
rating - рейтинт фильма на Кинопоиске
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
1) Напишите метод setReleaseYear, который будет принимать число и устанавливать новый год выхода фильма,
|
||||||
|
равный этому числу. Этот метод не должен ничего возвращать.
|
||||||
|
При этом, минимальный год выхода фильма должен быть 1900. При попытке установить меньший год выхода, метод
|
||||||
|
всё-равно должен устанавливать год, равный 1900.
|
||||||
|
|
||||||
|
2) Установите год выхода фильма a на 1998, используя метод setReleaseYear. Напечатайте фильм.
|
||||||
|
Попробуйте установить год выхода, равный 1600 Напечатайте фильм.
|
||||||
|
|
||||||
|
|
||||||
|
3) Напишите метод void addVote(float x), который будет имитировать проставление оценки x фильму одним пользователем
|
||||||
|
numVotes должен увеличиться на 1 и rating должен тоже изменится по формуле
|
||||||
|
|
||||||
|
новыйРейтинг = (старыйРейтиг * староеКоличествоГолосов + x) / (староеКоличествоГолосов + 1)
|
||||||
|
|
||||||
|
4) У данного фильма 4 голоса со средней оценкой 8.0. Добавьте ещё одну оценку, равную 10.0.
|
||||||
|
Напечатайте фильм, новый рейтинг фильма должен быть равен 8.4.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
struct Movie
|
||||||
|
{
|
||||||
|
char title[100];
|
||||||
|
int releaseYear;
|
||||||
|
int numVotes;
|
||||||
|
float rating;
|
||||||
|
|
||||||
|
|
||||||
|
void print() const
|
||||||
|
{
|
||||||
|
cout << title << ", releaseYear = " << releaseYear << ", rating = " << rating
|
||||||
|
<< " (" << numVotes << " votes)" << endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Movie a = {"Dark City", 2000, 4, 8.0};
|
||||||
|
a.print();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
struct Movie
|
||||||
|
{
|
||||||
|
char title[100];
|
||||||
|
int releaseYear;
|
||||||
|
int numVotes;
|
||||||
|
float rating;
|
||||||
|
|
||||||
|
void setReleaseYear(int year)
|
||||||
|
{
|
||||||
|
releaseYear = year;
|
||||||
|
if (releaseYear < 1900)
|
||||||
|
releaseYear = 1900;
|
||||||
|
}
|
||||||
|
|
||||||
|
void addVote(int x)
|
||||||
|
{
|
||||||
|
rating = (rating * numVotes + x) / (numVotes + 1);
|
||||||
|
numVotes += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print() const
|
||||||
|
{
|
||||||
|
cout << title << ", releaseYear = " << releaseYear << ", rating = " << rating
|
||||||
|
<< " (" << numVotes << " votes)" << endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Movie a = {"Dark City", 2000, 4, 8.0};
|
||||||
|
a.print();
|
||||||
|
|
||||||
|
a.setReleaseYear(1998);
|
||||||
|
a.print();
|
||||||
|
|
||||||
|
a.setReleaseYear(1600);
|
||||||
|
a.print();
|
||||||
|
|
||||||
|
a.addVote(10.0);
|
||||||
|
a.print();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
Ключевое слово this
|
||||||
|
|
||||||
|
Используя указатель this внутри структуры, можно узнать адрес объекта.
|
||||||
|
Например, если метод был вызван таким образом:
|
||||||
|
a.printThis();
|
||||||
|
то внутри метода this будет означать адрес объекта a
|
||||||
|
|
||||||
|
С помощью этого указателя можно доступаться до полей класса.
|
||||||
|
Например, title и this->title это одно и то же внутри методов структуры.
|
||||||
|
|
||||||
|
this можно использовать, если имя аргумента метода совпадает с одним из полей, как, например, в методе setPrice
|
||||||
|
Внутри метода setPrice поле price перекрывается аргументом price. Но можно всё-равно доступиться до поля price, используя указатель this
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
struct Book
|
||||||
|
{
|
||||||
|
char title[100];
|
||||||
|
float price;
|
||||||
|
int pages;
|
||||||
|
|
||||||
|
void printThis() const
|
||||||
|
{
|
||||||
|
cout << this << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void printTitle() const
|
||||||
|
{
|
||||||
|
cout << title << endl;
|
||||||
|
cout << this->title << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setPrice(float price)
|
||||||
|
{
|
||||||
|
this->price = price;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Book a = {"War and Peace", 1700, 900};
|
||||||
|
|
||||||
|
cout << &a << endl;
|
||||||
|
a.printThis();
|
||||||
|
|
||||||
|
a.printTitle();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
/*
|
||||||
|
Конструктор
|
||||||
|
|
||||||
|
Конструктор - это специальный метод, который вызывается при создании объекта
|
||||||
|
|
||||||
|
Конструктор Book(const char aTitle[], float aPrice, int aPages) принимает три аргумента и задаёт
|
||||||
|
этими аргументами поля класса, а также печатает на экран слово Constructor.
|
||||||
|
|
||||||
|
Конструктор вызывается в строке Book a = Book("War and Peace", 1700, 900).
|
||||||
|
В этом примере конструктор делает то же самое, что и обычная инициализация структуры: Book a = {"War and Peace", 1700, 900};
|
||||||
|
Преимущество конструктора по сравнению с обычной инициализации структур состоит в том, что программист может сам задать то,
|
||||||
|
что будет происходить при создании объекта.
|
||||||
|
|
||||||
|
|
||||||
|
Напоминание:
|
||||||
|
Функция strcpy из библиотеки string.h языка C принимает на вход 2 строки и просто копирует
|
||||||
|
содержимое второй строки в первую строку.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cmath>
|
||||||
|
#include <string.h>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
struct Book
|
||||||
|
{
|
||||||
|
char title[100];
|
||||||
|
float price;
|
||||||
|
int pages;
|
||||||
|
|
||||||
|
Book(const char aTitle[], float aPrice, int aPages)
|
||||||
|
{
|
||||||
|
cout << "Constructor" << endl;
|
||||||
|
strcpy(title, aTitle);
|
||||||
|
price = aPrice;
|
||||||
|
pages = aPages;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void print() const
|
||||||
|
{
|
||||||
|
std::cout << title << ", price = " << price << ", pages = " << pages << std::endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Book a = Book("War and Peace", 1700, 900);
|
||||||
|
a.print();
|
||||||
|
|
||||||
|
Book b = Book("The Great Gatsby", 800, -600);
|
||||||
|
b.print();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Предположим, что программист, работая с наши классом Book, ошибся в конструкторе и установил у книги отрицательное количество страниц.
|
||||||
|
|
||||||
|
Измените конструктор таким образом, чтобы программа не создавала объект с отрицательным числом страниц.
|
||||||
|
Вместо этого она должна писать сообщение об ошибке и выходить из программы.
|
||||||
|
Для выхода из программы можно использовать функцию std::exit(1) из библиотеки <cstdlib>
|
||||||
|
|
||||||
|
|
||||||
|
2) Конструкторы можно перегружать также, как и обычные функции и методы.
|
||||||
|
Добавьте новый конструктор, который не будет принимать никаких аргументов и будет создавать объект с полями равными
|
||||||
|
title: "Default" price: 0 pages: 0
|
||||||
|
Вызовите этот конструктор из main
|
||||||
|
|
||||||
|
Конструктор, который не принимает аргументов, называется конструктором по умолчанию.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
3) Конструкторы можно перегружать также, как и обычные функции и методы.
|
||||||
|
Добавьте новый конструктор, который будет принимать объект типа Book (по константной ссылке)
|
||||||
|
и будет задавать поля текущего объекта, используя поля аргумента
|
||||||
|
Вызовите этот конструктор из main
|
||||||
|
|
||||||
|
Конструктор, который создаёт объект, используя объект такого-же типа, называется конструктором копирования.
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cmath>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <string.h>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
struct Book
|
||||||
|
{
|
||||||
|
char title[100];
|
||||||
|
float price;
|
||||||
|
int pages;
|
||||||
|
|
||||||
|
Book(const char aTitle[], float aPrice, int aPages)
|
||||||
|
{
|
||||||
|
cout << "Constructor" << endl;
|
||||||
|
strcpy(title, aTitle);
|
||||||
|
price = aPrice;
|
||||||
|
pages = aPages;
|
||||||
|
|
||||||
|
if (pages < 0)
|
||||||
|
{
|
||||||
|
cout << "Error! Number of pages can't be negative!" << endl;
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Book()
|
||||||
|
{
|
||||||
|
cout << "Default Construtor" << endl;
|
||||||
|
strcpy(title, "Default");
|
||||||
|
price = 0;
|
||||||
|
pages = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Book(const Book& b)
|
||||||
|
{
|
||||||
|
cout << "Copy Construtor" << endl;
|
||||||
|
strcpy(title, b.title);
|
||||||
|
price = b.price;
|
||||||
|
pages = b.pages;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void print() const
|
||||||
|
{
|
||||||
|
cout << title << ", price = " << price << ", pages = " << pages << endl << endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Book a = Book("War and Peace", 1700, 900);
|
||||||
|
a.print();
|
||||||
|
|
||||||
|
Book b = Book();
|
||||||
|
b.print();
|
||||||
|
|
||||||
|
Book c = Book(a);
|
||||||
|
c.print();
|
||||||
|
|
||||||
|
Book d = Book("The Great Gatsby", 800, -600);
|
||||||
|
d.print();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
Сокрытие данных - это разделение данных и функций абстрактного объекта на открытые (видимые извне) и скрытые (видимые только внутри самого объекта)
|
||||||
|
В языке C++ это реализуется с помощью модификаторов доступа public и private
|
||||||
|
|
||||||
|
Все поля и методы объявленные в секции public называются публичными и могут быть доступны извне структуры
|
||||||
|
Все поля и методы объявленные в секции private называются приватными и не могут быть доступны извне структуры
|
||||||
|
Приватные поля и методы могут быть доступны только в методах самого структуры (а также в друзьях, но об этом позже)
|
||||||
|
|
||||||
|
|
||||||
|
Назначение сокрытия данных заключается в том, чтобы объекты нельзя было 'поломать' извне
|
||||||
|
'Поломать' тут означает задать поля объекта бессмысленным образом
|
||||||
|
|
||||||
|
Например, в нашем примере мы бы могли поломать объект просто сделав поля price или pages отрицательными
|
||||||
|
a.pages = -100;
|
||||||
|
но благодаря тому, что поле pages является приватным, это сделать нельзя.
|
||||||
|
|
||||||
|
|
||||||
|
Учитывая проверку в конструкторе, получается, что поля pages и price в принципе никогда не смогут стать отрицательными.
|
||||||
|
Таким образом мы уберегли себя от возникновения ошибок при неправильном задании полей структуры.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cmath>
|
||||||
|
#include <string.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
struct Book
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
char title[100];
|
||||||
|
float price;
|
||||||
|
int pages;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Book(const char aTitle[], float aPrice, int aPages)
|
||||||
|
{
|
||||||
|
if (aPages < 0 || aPrice < 0 || strlen(aTitle) >= 100)
|
||||||
|
{
|
||||||
|
cout << "Error while creating Book!" << endl;
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(title, aTitle);
|
||||||
|
price = aPrice;
|
||||||
|
pages = aPages;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void print() const
|
||||||
|
{
|
||||||
|
cout << title << ", price = " << price << ", pages = " << pages << endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Book a = Book("War and Peace", 1700, 900);
|
||||||
|
a.print();
|
||||||
|
|
||||||
|
a.pages = -100;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
/*
|
||||||
|
Синтаксис инициализации с помощью коструктора
|
||||||
|
|
||||||
|
Язык C++ имеет очень длинную историю и на её протяжении в язык добавлялись новые возможности
|
||||||
|
В итоге в языке часто можно сделать одно и то же разными методами.
|
||||||
|
|
||||||
|
В частности, вызвать конструктор можно 5-ю разными способами.
|
||||||
|
В этой программе строки для создания книг a, b, c, d, e делают одно и то же, несмотря, что имеют разный синтаксис
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cmath>
|
||||||
|
#include <string.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
struct Book
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
char title[100];
|
||||||
|
float price;
|
||||||
|
int pages;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Book(const char aTitle[], float aPrice, int aPages)
|
||||||
|
{
|
||||||
|
cout << "Constructor" << endl;
|
||||||
|
strcpy(title, aTitle);
|
||||||
|
price = aPrice;
|
||||||
|
pages = aPages;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void print() const
|
||||||
|
{
|
||||||
|
cout << title << ", price = " << price << ", pages = " << pages << endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Book a = Book("War and Peace", 1000, 500);
|
||||||
|
|
||||||
|
Book b("War and Peace", 1000, 500);
|
||||||
|
|
||||||
|
Book c = {"War and Peace", 1000, 500};
|
||||||
|
|
||||||
|
Book d = Book{"War and Peace", 1000, 500};
|
||||||
|
|
||||||
|
Book e {"War and Peace", 1000, 500};
|
||||||
|
|
||||||
|
a.print();
|
||||||
|
b.print();
|
||||||
|
c.print();
|
||||||
|
d.print();
|
||||||
|
e.print();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
1) Добавьте к классу конструктор по умолчанию:
|
||||||
|
|
||||||
|
Book()
|
||||||
|
{
|
||||||
|
cout << "Default Constructor" << endl;
|
||||||
|
strcpy(title, "default");
|
||||||
|
price = 0;
|
||||||
|
pages = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Создайте с помощью этого конструктора 5 книг, вызвав его 5-ю разными способами
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cmath>
|
||||||
|
#include <string.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
struct Book
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
char title[100];
|
||||||
|
float price;
|
||||||
|
int pages;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Book(const char aTitle[], float aPrice, int aPages)
|
||||||
|
{
|
||||||
|
cout << "Constructor" << endl;
|
||||||
|
strcpy(title, aTitle);
|
||||||
|
price = aPrice;
|
||||||
|
pages = aPages;
|
||||||
|
}
|
||||||
|
|
||||||
|
Book()
|
||||||
|
{
|
||||||
|
cout << "Default Constructor" << endl;
|
||||||
|
strcpy(title, "default");
|
||||||
|
price = 0;
|
||||||
|
pages = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void print() const
|
||||||
|
{
|
||||||
|
cout << title << ", price = " << price << ", pages = " << pages << endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Book a = Book();
|
||||||
|
|
||||||
|
// Book b(); // этот способ не работает, так как его невозможно отличить от объявления функции (зато добавился способ f)
|
||||||
|
|
||||||
|
Book c = {};
|
||||||
|
|
||||||
|
Book d = Book{};
|
||||||
|
|
||||||
|
Book e {};
|
||||||
|
|
||||||
|
Book f; // в отличии от переменных базовых типов, тут произойдёт инициализация (конструктором по умолчанию)
|
||||||
|
|
||||||
|
a.print();
|
||||||
|
c.print();
|
||||||
|
d.print();
|
||||||
|
e.print();
|
||||||
|
f.print();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
Классы. Ключевое слово class.
|
||||||
|
|
||||||
|
На самом деле классы мы уже прошли. Структуры с методоми из предыдущих файлов это и есть классы.
|
||||||
|
Для объявления класса может использоваться ключевое слово class.
|
||||||
|
|
||||||
|
Разница между этими ключевым словами минимальна
|
||||||
|
- при использовании struct все поля и методы по умолчанию публичны
|
||||||
|
- при использовании class все поля и методы по умолчанию приватны
|
||||||
|
Но, так как мы указываем private и public для всех членов, то разницы нет вообще.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cmath>
|
||||||
|
#include <string.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
class Book
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
char title[100];
|
||||||
|
float price;
|
||||||
|
int pages;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Book(const char aTitle[], float aPrice, int aPages)
|
||||||
|
{
|
||||||
|
if (aPages < 0 || aPrice < 0 || strlen(aTitle) >= 100)
|
||||||
|
{
|
||||||
|
cout << "Error while creating Book!" << endl;
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(title, aTitle);
|
||||||
|
price = aPrice;
|
||||||
|
pages = aPages;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void print() const
|
||||||
|
{
|
||||||
|
cout << title << ", price = " << price << ", pages = " << pages << endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Book a = Book("War and Peace", 1700, 900);
|
||||||
|
a.print();
|
||||||
|
}
|
||||||
56
seminar02_encapsulation/classroom_tasks/code/0book/10m.cpp
Normal file
56
seminar02_encapsulation/classroom_tasks/code/0book/10m.cpp
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
Некоторые замечания по оформлению
|
||||||
|
|
||||||
|
1) Как правило в классе сначала описываются публичные методы, а потом приватные
|
||||||
|
Так делают потому что если другой программист захочет воспользоваться вашим классом,
|
||||||
|
то его будет в первую очередь будет интересовать что ваш класс может делать
|
||||||
|
и уже потом его будет интересовать строение класса.
|
||||||
|
|
||||||
|
|
||||||
|
2) Приватные поля класса желательно называть так, чтобы их можно было отличить от обычных переменных
|
||||||
|
Это может сильно упростить понимание при написании/использовании больших програм и библиотек
|
||||||
|
В данном курсе мы будем называть приватные поля начиная с буквы m
|
||||||
|
Например, mTitle вместо title
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cmath>
|
||||||
|
#include <string.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
class Book
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Book(const char title[], float price, int pages)
|
||||||
|
{
|
||||||
|
if (pages < 0 || price < 0 || strlen(title) >= 100)
|
||||||
|
{
|
||||||
|
cout << "Error while creating Book!" << endl;
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
strcpy(mTitle, title);
|
||||||
|
mPrice = price;
|
||||||
|
mPages = pages;
|
||||||
|
}
|
||||||
|
|
||||||
|
void print() const
|
||||||
|
{
|
||||||
|
cout << mTitle << ", price = " << mPrice << ", pages = " << mPages << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
char mTitle[100];
|
||||||
|
float mPrice;
|
||||||
|
int mPages;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Book a = Book("War and Peace", 1700, 900);
|
||||||
|
a.print();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
/*
|
||||||
|
Это программа на языке C, для компиляции:
|
||||||
|
gcc 00point.c
|
||||||
|
./a.out
|
||||||
|
|
||||||
|
Опишем структуру точки в двумерном пространстве на языке C
|
||||||
|
|
||||||
|
Точка задаётся двумя координатами x и y
|
||||||
|
Так как эта структура имеет очень маленький размер (всего 8 байт), то в функции
|
||||||
|
её можно передавать по значению, а не по константному указателю.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
struct point
|
||||||
|
{
|
||||||
|
float x, y;
|
||||||
|
};
|
||||||
|
typedef struct point Point;
|
||||||
|
|
||||||
|
|
||||||
|
void point_print(Point a)
|
||||||
|
{
|
||||||
|
printf("(%.2f, %.2f)\n", a.x, a.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Point a = {7.2, 3.1};
|
||||||
|
Point b = {-4.6, 2.4};
|
||||||
|
|
||||||
|
point_print(a);
|
||||||
|
point_print(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Напишите функцию point_add,
|
||||||
|
которая будет принимать две точки и возвращать их сумму
|
||||||
|
|
||||||
|
2) Напишите функцию point_norm,
|
||||||
|
которая будет принимать точку и возвращать расстояние до этой точки от начала координат
|
||||||
|
Будем называть расстояние от точки до начала координат нормой точки
|
||||||
|
Для вычисления корня числа можно использовать функцию sqrt из math.h
|
||||||
|
|
||||||
|
3) Напишите функцию point_mult,
|
||||||
|
которая будет принимать на вход точку и число k типа float и возвращать точку, координаты которой
|
||||||
|
равны координатам изначальной точки, умноженные на число k
|
||||||
|
|
||||||
|
4) Напишите функцию point_normalize,
|
||||||
|
которая будет принимать точку по указателю и делить координаты точки на норму точки
|
||||||
|
Эта функция не должна ничего возвращать
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
Это программа на языке C, для компиляции:
|
||||||
|
gcc 00point_solution.c
|
||||||
|
./a.out
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
|
||||||
|
struct point
|
||||||
|
{
|
||||||
|
float x, y;
|
||||||
|
};
|
||||||
|
typedef struct point Point;
|
||||||
|
|
||||||
|
|
||||||
|
void point_print(Point a)
|
||||||
|
{
|
||||||
|
printf("(%.2f, %.2f)\n", a.x, a.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
Point point_add(Point a, Point b)
|
||||||
|
{
|
||||||
|
Point result = {a.x + b.x, a.y + b.y};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float point_norm(Point a)
|
||||||
|
{
|
||||||
|
return sqrtf(a.x * a.x + a.y * a.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
Point point_mult(Point a, float k)
|
||||||
|
{
|
||||||
|
Point result = {k * a.x, k * a.y};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void point_normalize(Point* pa)
|
||||||
|
{
|
||||||
|
float norm = point_norm(*pa);
|
||||||
|
pa->x /= norm;
|
||||||
|
pa->y /= norm;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Point a = {7.2, 3.1};
|
||||||
|
Point b = {-4.6, 2.4};
|
||||||
|
|
||||||
|
point_print(a);
|
||||||
|
point_print(b);
|
||||||
|
|
||||||
|
Point c = point_add(a, b);
|
||||||
|
point_print(c);
|
||||||
|
|
||||||
|
point_print(point_mult(c, 1.5f));
|
||||||
|
|
||||||
|
point_normalize(&c);
|
||||||
|
point_print(c);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
/*
|
||||||
|
Это программа на языке C++, для компиляции:
|
||||||
|
g++ 01point.cpp
|
||||||
|
|
||||||
|
Та же самая точка, но на языке C++
|
||||||
|
|
||||||
|
В этом файле была видоизменена программа из предыдущего файла.
|
||||||
|
Были использованы перегруженные операторы для более удобного сложения и умножения точек.
|
||||||
|
Также была использована ссылка вместо указателя в функции pointNormalize.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <cmath>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
struct Point
|
||||||
|
{
|
||||||
|
float x, y;
|
||||||
|
};
|
||||||
|
|
||||||
|
void pointPrint(Point a)
|
||||||
|
{
|
||||||
|
cout << std::setprecision(2) << "(" << a.x << ", " << a.y << ")" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Point operator+(Point a, Point b)
|
||||||
|
{
|
||||||
|
Point result = {a.x + b.x, a.y + b.y};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float pointNorm(Point a)
|
||||||
|
{
|
||||||
|
return std::sqrt(a.x * a.x + a.y * a.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
Point operator*(Point a, float k)
|
||||||
|
{
|
||||||
|
Point result = {k * a.x, k * a.y};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void pointNormalize(Point& a)
|
||||||
|
{
|
||||||
|
float norm = pointNorm(a);
|
||||||
|
a.x /= norm;
|
||||||
|
a.y /= norm;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Point a = {7.2, 3.1};
|
||||||
|
Point b = {-4.6, 2.4};
|
||||||
|
|
||||||
|
pointPrint(a);
|
||||||
|
pointPrint(b);
|
||||||
|
|
||||||
|
Point c = a + b;
|
||||||
|
pointPrint(c);
|
||||||
|
|
||||||
|
pointPrint(c * 1.5f);
|
||||||
|
|
||||||
|
pointNormalize(c);
|
||||||
|
pointPrint(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
1) Инкапсулируйте функции operator+, pointNorm, operator* и pointNormalize
|
||||||
|
Их нужно сделать методами, то есть положить внутрь структуры Point
|
||||||
|
Не забудьте сделать соответствующие методы константными
|
||||||
|
|
||||||
|
2) Можно сделать то же самое с функцией printPoint, а можно поступить по-другому
|
||||||
|
и перегрузить оператор << для типов std::ostream и Point
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
Обратите внимание на следующие моменты в этом решении:
|
||||||
|
|
||||||
|
1) При переносе функций внутрь класса у них стало на 1 аргумент меньше
|
||||||
|
Просто потому что все методы неявно принимают вызывающий их объект
|
||||||
|
|
||||||
|
Например, если a это точка, то при вызове:
|
||||||
|
a.norm()
|
||||||
|
|
||||||
|
метод norm 'знает', что его вызвала имено точка a и может доступаться до её полей x и y
|
||||||
|
|
||||||
|
|
||||||
|
2) Перегруженные операторы тоже могут быть методами
|
||||||
|
При этом оператор преобразуется следующим образом:
|
||||||
|
|
||||||
|
a @ b -> a.operator@(b)
|
||||||
|
где на месте @ может быть любой бинарный оператор
|
||||||
|
|
||||||
|
Например, сложение преобразуется так:
|
||||||
|
a + b -> a.operator+(b)
|
||||||
|
|
||||||
|
Обратите внимание, что перегруженный оператор может стать методом только первого аргумента
|
||||||
|
|
||||||
|
|
||||||
|
3) Перегрузка оператора << для типов std::ostream и Point
|
||||||
|
Для более удобного вывода на экран можно перегрузить этот оператор
|
||||||
|
|
||||||
|
Когда компилятор встретит выражение cout << a где cout имеет тип std::ostream, а имеет тип Point
|
||||||
|
то он вызовет эту функцию.
|
||||||
|
Эта функция должна вызывать ссылку на cout так как результатом cout << a тоже должен быть cout
|
||||||
|
чтобы мы могли выводить цепочкой, например так: cout << a << b << endl
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <cmath>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
struct Point
|
||||||
|
{
|
||||||
|
float x, y;
|
||||||
|
|
||||||
|
Point operator+(Point b) const
|
||||||
|
{
|
||||||
|
Point result = {x + b.x, y + b.y};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float norm() const
|
||||||
|
{
|
||||||
|
return std::sqrt(x * x + y * y);
|
||||||
|
}
|
||||||
|
|
||||||
|
Point operator*(float k) const
|
||||||
|
{
|
||||||
|
Point result = {k * x, k * y};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void normalize()
|
||||||
|
{
|
||||||
|
float normv = norm();
|
||||||
|
x /= normv;
|
||||||
|
y /= normv;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, Point a)
|
||||||
|
{
|
||||||
|
out << std::setprecision(2) << "(" << a.x << ", " << a.y << ")";
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Point a = {7.2, 3.1};
|
||||||
|
Point b = {-4.6, 2.4};
|
||||||
|
|
||||||
|
cout << a << endl;
|
||||||
|
cout << b << endl;
|
||||||
|
|
||||||
|
Point c = a + b;
|
||||||
|
cout << c << endl;
|
||||||
|
|
||||||
|
cout << c * 1.5f << endl;
|
||||||
|
|
||||||
|
c.normalize();
|
||||||
|
cout << c << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <cmath>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
struct Point
|
||||||
|
{
|
||||||
|
float x, y;
|
||||||
|
|
||||||
|
Point operator*(float k) const
|
||||||
|
{
|
||||||
|
Point result = {k * x, k * y};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, Point a)
|
||||||
|
{
|
||||||
|
out << std::setprecision(2) << "(" << a.x << ", " << a.y << ")";
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Point a = {2.1, 1.5};
|
||||||
|
|
||||||
|
cout << a * 2 << endl;
|
||||||
|
cout << 2 * a << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) В этой программе выражение a * 2 вычисляется правильно, но
|
||||||
|
выражение 2 * a даёт ошибку.
|
||||||
|
|
||||||
|
Из-за чего это происходит? Исправьте ситуацию так, чтобы выражение 2 * a также вычислялось.
|
||||||
|
|
||||||
|
|
||||||
|
2) Можно ли сделать перегруженный оператор << методом класса Point?
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
Решения:
|
||||||
|
|
||||||
|
1) Выражение a * 2 вычисляется так как есть перегруженный оператор a.operator*(2)
|
||||||
|
Выражение 2 * a даёт ошибку так как не было перегруженного оператора operator*(2, a)
|
||||||
|
|
||||||
|
Но его можно просто написать, как это сделано ниже.
|
||||||
|
|
||||||
|
Сделать этот оператор методом мы не можем, так как перегруженный оператор может быть методом
|
||||||
|
только первого аргумента, первый аргумент в данном случае это число целочисленного типа float.
|
||||||
|
Добавить метод в тип float мы не можем, так как float это вообще не класс.
|
||||||
|
|
||||||
|
Замечание: Литерал 2 на самом деле имеет тип int, но int может конвертироваться во float если нужно
|
||||||
|
|
||||||
|
|
||||||
|
2) Можно ли сделать перегруженный оператор << методом класса Point?
|
||||||
|
|
||||||
|
Нет, нельзя. Перегруженный оператор может быть методом только первого аргумента.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <cmath>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
struct Point
|
||||||
|
{
|
||||||
|
float x, y;
|
||||||
|
|
||||||
|
Point operator*(float k) const
|
||||||
|
{
|
||||||
|
Point result = {k * x, k * y};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
Point operator*(float k, Point a)
|
||||||
|
{
|
||||||
|
return a * k;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, Point a)
|
||||||
|
{
|
||||||
|
out << std::setprecision(2) << "(" << a.x << ", " << a.y << ")";
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Point a = {2.1, 1.5};
|
||||||
|
|
||||||
|
cout << a * 2 << endl;
|
||||||
|
cout << 2 * a << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,124 @@
|
||||||
|
/*
|
||||||
|
До этого момента поля x и y класса Point были публичными
|
||||||
|
|
||||||
|
Обычно, мы не хотим делать поля публичными, так как мы не хотим, чтобы поля могли бы быть заданы некоректным значением извне класса.
|
||||||
|
Однако, в случае класса Point некорректных значений для x и y просто не существует - любое вещественное число будет
|
||||||
|
корректным для значения координаты точки.
|
||||||
|
Поэтому нет ничего плохого, чтобы сделать x и y публичными для класса Point
|
||||||
|
|
||||||
|
|
||||||
|
Но давайте сделаем класс с немного более сложным поведением.
|
||||||
|
Точка RestrictedPoint - это будет точка, которая может находится только в квадрате [0,1]x[0,1]
|
||||||
|
То есть поле x может принимать значения только от 0 до 1 и поле y может принимать значения только от 0 до 1.
|
||||||
|
|
||||||
|
Сделаем поля x и y приватными (и назовём их mx и my)
|
||||||
|
Теперь до них можно будет доступиться только в методах класса RestrictedPoint и в друзьях.
|
||||||
|
|
||||||
|
Чтобы можно было работать с этими полями вне класса напишем методы
|
||||||
|
getx, gety, setx, sety
|
||||||
|
Такие методы для получения полей и записи в поля класса называются геттерами и сеттерами
|
||||||
|
Функции getx и gety просто возвращают соответствующие координаты
|
||||||
|
Функции setx и sety меняют соответствующие координаты и следят, чтобы они находились в диапазоне от 0 до 1
|
||||||
|
|
||||||
|
|
||||||
|
Нам понадобится стандартная функция std::clamp из <algorithm>, которая принимает на вход три числа и
|
||||||
|
если первое число находится в промежутке между вторым и третьим, то clamp возвращает первое число
|
||||||
|
если первое число меньше, чем второе, то clamp возвращает второе число
|
||||||
|
если первое число больше, чем третье, то clamp возвращает третье число
|
||||||
|
Грубо говоря clamp ограничивает число в заданых пределах
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cmath>
|
||||||
|
#include <algorithm>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class RestrictedPoint
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
float mx, my;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
RestrictedPoint(float x, float y)
|
||||||
|
{
|
||||||
|
mx = std::clamp(x, 0.0f, 1.0f);
|
||||||
|
my = std::clamp(y, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
RestrictedPoint()
|
||||||
|
{
|
||||||
|
mx = 0;
|
||||||
|
my = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
float getx() const
|
||||||
|
{
|
||||||
|
return mx;
|
||||||
|
}
|
||||||
|
|
||||||
|
float gety() const
|
||||||
|
{
|
||||||
|
return my;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setx(float x)
|
||||||
|
{
|
||||||
|
mx = std::clamp(x, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sety(float y)
|
||||||
|
{
|
||||||
|
my = std::clamp(y, 0.0f, 1.0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
float norm() const
|
||||||
|
{
|
||||||
|
return std::sqrt(mx*mx + my*my);
|
||||||
|
}
|
||||||
|
|
||||||
|
RestrictedPoint operator+(const RestrictedPoint& right) const
|
||||||
|
{
|
||||||
|
RestrictedPoint result;
|
||||||
|
result.mx = std::clamp(mx + right.mx, 0.0f, 1.0f);
|
||||||
|
result.my = std::clamp(my + right.my, 0.0f, 1.0f);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, const RestrictedPoint& a)
|
||||||
|
{
|
||||||
|
out << "(" << a.getx() << ", " << a.gety() << ")";
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
RestrictedPoint a = RestrictedPoint(0.5, 1.2);
|
||||||
|
cout << a << endl;
|
||||||
|
|
||||||
|
a.setx(2);
|
||||||
|
cout << a << endl;
|
||||||
|
|
||||||
|
a.sety(-5);
|
||||||
|
cout << a << endl;
|
||||||
|
|
||||||
|
|
||||||
|
RestrictedPoint b = RestrictedPoint(0.4, 0.2);
|
||||||
|
RestrictedPoint c = RestrictedPoint(0.8, 0.4);
|
||||||
|
cout << c + b << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
1) Добавьте к классу RestrictedPoint оператор умножения на число типа float
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
Создадим свою строку
|
||||||
|
|
||||||
|
Один из самых главных недостатков языка C это работа со строками.
|
||||||
|
Строки в языке C это просто массивы элементов типа char
|
||||||
|
char str[100]; или char* p = malloc(100);
|
||||||
|
|
||||||
|
В языке C работать со строками очень неудобно по многим причинам:
|
||||||
|
- Нужно постоянно следить за тем, чтобы строка умещалась в памяти, которая под нею выделена.
|
||||||
|
- Строку можно выделить на Стеке, используя обычный массив, и тогда её вместимость нельзя будет увеличить,
|
||||||
|
а можно выделить в Куче, но тогда придётся самостоятельно выделять и освобождать память
|
||||||
|
и следить, чтобы не произошли утечки памяти.
|
||||||
|
- Строки нельзя просто копировать, сравнивать, складывать и т. д. Для этого нужно использовать
|
||||||
|
специальные функции типа strcpy и другие функции из библиотеки <string.h>.
|
||||||
|
|
||||||
|
|
||||||
|
Создадим же удобный класс строки
|
||||||
|
Такой чтобы можно было удобно создавать строки, приравнивать, складывать и сравнивать.
|
||||||
|
Не заботясь о выделении/удалении памяти, и о том, что строка помещается в выделенную память.
|
||||||
|
|
||||||
|
Чтобы можно было писать вот такой код:
|
||||||
|
|
||||||
|
String a = "Cat";
|
||||||
|
String b = "Dog";
|
||||||
|
cout << a << " " << b << endl;
|
||||||
|
|
||||||
|
String c = "Mouse";
|
||||||
|
c = a + b;
|
||||||
|
c += "Bear";
|
||||||
|
|
||||||
|
if (c == "CatDogBear")
|
||||||
|
cout << "Yes" << endl;
|
||||||
|
|
||||||
|
c = a;
|
||||||
|
cout << c << endl;
|
||||||
|
|
||||||
|
|
||||||
|
(String в переводе с английского это Строка)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main() {}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,165 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Создадим строку, которая при создании (т.е в конструкторе) будет автоматически выделять необходимую память в Куче.
|
||||||
|
В чём-то реализация этой строки будет похожа на реализацию динамического массива из прошлого семестра.
|
||||||
|
|
||||||
|
У класса строки 3 поля:
|
||||||
|
|
||||||
|
mSize - размер - количество символов в строке (без учёта \0)
|
||||||
|
mCapacity - вместимость - количество выделенной памяти в Куче
|
||||||
|
mpData - указатель на выделенную память в Куче. В этой памяти строка будет иметь такой же вид, как и строка языка C.
|
||||||
|
В частности она будет иметь символ '\0' на конце.
|
||||||
|
Символ '\0' на конце оставим, чтобы было удобно конвертировать нашу строку в строку в стиле C.
|
||||||
|
|
||||||
|
|
||||||
|
Размер и вместимость это разные величины.
|
||||||
|
|
||||||
|
Например, для хранения строки "Cat" может быть выделено памяти под 10 символов, хоть и под эту строку было бы достаточно всего 4.
|
||||||
|
Представьте, что у вас есть длинная строка и вы хотите удалить последний символ в ней.
|
||||||
|
Если бы мы не хранили вместимость, а всегда выделяли памяти в притык, то в этом простом случае нам бы пришлось
|
||||||
|
перевыделять память и копировать всю строку в новую память.
|
||||||
|
Если же мы храним вместимость, то достаточно всего лишь уменьшить размер на 1 и поставит \0 в новый конец строки.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Теперь создадим конструктор, который будет выделять память и заполнять его нужным образом
|
||||||
|
|
||||||
|
Конструктор String(const char* str) конструирует нашу строку из строки в стиле C.
|
||||||
|
Принимаем на вход именно константную строку, так как в этом случае в конструктор можно будет
|
||||||
|
передать как константные, так и неконстантые строки.
|
||||||
|
Если бы мы написали так String(char* str) , то в конструктор нельзя было бы передать константные строки.
|
||||||
|
|
||||||
|
|
||||||
|
В строках:
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
мы находим размер переданной строки (strlen не используем, чтобы не связываться со старой библиотекой)
|
||||||
|
Вместимость на 1 больше, так как нужно учесть память под символ /0
|
||||||
|
|
||||||
|
|
||||||
|
В строке:
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
выделяем необходимую память
|
||||||
|
|
||||||
|
|
||||||
|
В строках:
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i] != '\0'; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
|
||||||
|
копируем содержимое переданной строки в только что выделенную память.
|
||||||
|
|
||||||
|
|
||||||
|
Другие методы класса String:
|
||||||
|
|
||||||
|
getSize - возвращает размер строки
|
||||||
|
getCapacity - возвращает вместимость строки
|
||||||
|
cStr - возвращает строку в стиле C, то есть указатель на массив из char-ов с конечным символом \0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i] != '\0'; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t getSize() const
|
||||||
|
{
|
||||||
|
return mSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getCapacity() const
|
||||||
|
{
|
||||||
|
return mCapacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* cStr() const
|
||||||
|
{
|
||||||
|
return mpData;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, const String& s)
|
||||||
|
{
|
||||||
|
out << s.cStr();
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Cat";
|
||||||
|
String b = "Dog";
|
||||||
|
String c = "Lion";
|
||||||
|
|
||||||
|
cout << a << endl << b << endl << c << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задание:
|
||||||
|
|
||||||
|
1) Создайте конструктор String(), который будет создавать пустую строку
|
||||||
|
(mSize = 0, mCapacity = 1, строка mpData содержит в себе 1 символ ('\0'))
|
||||||
|
|
||||||
|
Конструктор, который не принимает аргументов называется конструктором по умолчанию
|
||||||
|
|
||||||
|
|
||||||
|
2) Создайте конструктор String(size_t n, char a), который будет создавать строку из n символов a
|
||||||
|
(mSize = n, mCapacity = n + 1, строка mpData содержит в себе n + 1 символ (n раз a и '\0'))
|
||||||
|
|
||||||
|
|
||||||
|
2) Создайте конструктор String(const String& s), который будет создавать строку String из другой строки String
|
||||||
|
(mSize = s.mSize, mCapacity = s.mCapacity, строка mpData содержит в себе копию строки s.mpData)
|
||||||
|
|
||||||
|
Конструктор, который создаёт объект по другому объекту такого же типа называется конструктором копирования.
|
||||||
|
|
||||||
|
|
||||||
|
Протестируйте эти конструкторы:
|
||||||
|
String a;
|
||||||
|
cout << a << endl;
|
||||||
|
|
||||||
|
String b(10, 'q');
|
||||||
|
cout << b << endl;
|
||||||
|
|
||||||
|
String c("Cat");
|
||||||
|
cout << c << endl;
|
||||||
|
|
||||||
|
String d(c);
|
||||||
|
cout << d << endl;
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,104 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
cout << "Construtor from const char*" << endl;
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i] != '\0'; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String()
|
||||||
|
{
|
||||||
|
cout << "Default Construtor" << endl;
|
||||||
|
mSize = 0;
|
||||||
|
mCapacity = 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
mpData[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String(size_t n, char a)
|
||||||
|
{
|
||||||
|
cout << "Construtor n equal characters" << endl;
|
||||||
|
mSize = n;
|
||||||
|
mCapacity = n + 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
mpData[i] = a;
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String(const String& s)
|
||||||
|
{
|
||||||
|
cout << "Copy Constructor" << endl;
|
||||||
|
mSize = s.mSize;
|
||||||
|
mCapacity = s.mCapacity;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
mpData[i] = s.mpData[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize() const
|
||||||
|
{
|
||||||
|
return mSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getCapacity() const
|
||||||
|
{
|
||||||
|
return mCapacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* cStr() const
|
||||||
|
{
|
||||||
|
return mpData;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a;
|
||||||
|
cout << a << endl << endl;
|
||||||
|
|
||||||
|
String b(10, 'q');
|
||||||
|
cout << b << endl << endl;
|
||||||
|
|
||||||
|
|
||||||
|
String c = "Cat";
|
||||||
|
cout << c << endl << endl;
|
||||||
|
|
||||||
|
|
||||||
|
String d(c);
|
||||||
|
cout << c << endl << endl;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,109 @@
|
||||||
|
/*
|
||||||
|
Делегирующий конструктор
|
||||||
|
|
||||||
|
В разных конструкторах может быть повторяющийся код.
|
||||||
|
Повторений кода иногда можно избежать если писать один конструктор на основе уже написанного.
|
||||||
|
|
||||||
|
Это можно сделать с помощью синтаксиса так называемого делегирующего конструктора
|
||||||
|
После объявления конструктора, но перед его телом можно написать двоеточие и вызвать другой конструктор
|
||||||
|
|
||||||
|
Например:
|
||||||
|
|
||||||
|
String() : String("")
|
||||||
|
{
|
||||||
|
cout << "Default Constructor" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Этот конструктор сначала вызовет конструктор String(const char* str) с аргументом "" (то есть пустой строкой)
|
||||||
|
а потом исполнит тело данного коструктора (в данном случае напечатает Default Constructor).
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
cout << "Constructor" << endl;
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i] != '\0'; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String() : String("")
|
||||||
|
{
|
||||||
|
cout << "Default Constructor" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String(const String& s) : String(s.cStr())
|
||||||
|
{
|
||||||
|
cout << "Copy Constructor" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize() const
|
||||||
|
{
|
||||||
|
return mSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getCapacity() const
|
||||||
|
{
|
||||||
|
return mCapacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* cStr() const
|
||||||
|
{
|
||||||
|
return mpData;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a;
|
||||||
|
cout << "a = " << a << endl << endl;
|
||||||
|
|
||||||
|
|
||||||
|
String b = "Cat";
|
||||||
|
cout << "b = " << b << endl << endl;
|
||||||
|
|
||||||
|
|
||||||
|
String c(b);
|
||||||
|
cout << "c = " << c << endl << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
Попробуйте понять без запуска, что напечатает данная программа
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,113 @@
|
||||||
|
/*
|
||||||
|
В конструкторе мы выделили память с malloc, но нигде в программе её не освободили
|
||||||
|
Соответственно, в предыдущей программе у нас есть очень серьёзная ошибка - утечка памяти.
|
||||||
|
|
||||||
|
Где же нужно освобождать память?
|
||||||
|
Если память была выделена в конструкторе при создании объекта, то выделять её нужно при удалении объекта.
|
||||||
|
Для того, чтобы испольнить ваш код при удалении объекта существует специальный метод, который называется Деструктор.
|
||||||
|
|
||||||
|
|
||||||
|
Деструктор - это специальный метод, который вызывается тогда, когда объект уничтожается
|
||||||
|
Объекты, созданные на стеке удаляются при выходе из области видимости
|
||||||
|
|
||||||
|
|
||||||
|
Синтаксис деструктора такой:
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
cout << "Constructor of " << str << endl;
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i] != '\0'; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
cout << "Destructor of " << mpData << endl;
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t getSize() const
|
||||||
|
{
|
||||||
|
return mSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getCapacity() const
|
||||||
|
{
|
||||||
|
return mCapacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* cStr() const
|
||||||
|
{
|
||||||
|
return mpData;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Cat";
|
||||||
|
String b = "Dog";
|
||||||
|
|
||||||
|
if (true)
|
||||||
|
{
|
||||||
|
String c = "Lion";
|
||||||
|
}
|
||||||
|
|
||||||
|
String c = "Bear";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задание:
|
||||||
|
|
||||||
|
1) Что напечатает данная программа?
|
||||||
|
В каком порядке вызовутся конструкторы
|
||||||
|
|
||||||
|
|
||||||
|
2) Если создать строку String в цикле, то будут ли каждую итерацию вызываться конструкторы и деструкторы?
|
||||||
|
|
||||||
|
for (int i = 0; i < 10; ++i)
|
||||||
|
{
|
||||||
|
String s = "Elephant";
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
Оператор сложения
|
||||||
|
|
||||||
|
Оператор сложения для строк должен принимать 2 строки и возвращать новую строку, равную результату конкатенации двух строк
|
||||||
|
Если строка a = "Cat" , а строка b = "Mouse" , то их конкатенация это a + b = "CatMouse"
|
||||||
|
|
||||||
|
Оператор сложения должен принимать свои аргументы по константной ссылке
|
||||||
|
по ссылке, чтобы не копировать объект лишний раз при передаче в функцию
|
||||||
|
по константной, потому что мы не будем менять принимаемые объекты внутри функции
|
||||||
|
|
||||||
|
|
||||||
|
То есть прототип оператора сложения, если его делать с помощью обычной функции, должен выглядеть так:
|
||||||
|
|
||||||
|
String operator+(const String& a, const String& b)
|
||||||
|
|
||||||
|
|
||||||
|
Прототип оператора сложения, если его делать с помощью метода класса String, должен выглядеть так:
|
||||||
|
|
||||||
|
String operator+(const String& b) const
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
cout << "Constructor of " << str << endl;
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i] != '\0'; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String() : String("") {}
|
||||||
|
String(const String& s) : String(s.cStr()) {}
|
||||||
|
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
cout << "Destructor of " << mpData << endl;
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Cat";
|
||||||
|
String b = "Mouse";
|
||||||
|
|
||||||
|
cout << a + b << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задание:
|
||||||
|
|
||||||
|
1) Написать оператор сложения для строки String в виде свободной функции
|
||||||
|
В этом случае эту функцию нужно сделать дружественной классу String,
|
||||||
|
чтобы она имела доступ к приватным полям класса
|
||||||
|
|
||||||
|
2) Написать оператор сложения для строки String в виде метода класса String
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i] != '\0'; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String() : String("") {}
|
||||||
|
String(const String& s) : String(s.cStr()) {}
|
||||||
|
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
|
||||||
|
friend String operator+(const String& a, const String& b);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
String operator+(const String& a, const String& b)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
result.mSize = a.mSize + b.mSize;
|
||||||
|
result.mCapacity = result.mSize + 1;
|
||||||
|
result.mpData = (char*)std::malloc(sizeof(char) * result.mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < a.mSize; ++i)
|
||||||
|
result.mpData[i] = a.mpData[i];
|
||||||
|
|
||||||
|
for (size_t i = 0; i < b.mSize; ++i)
|
||||||
|
result.mpData[a.mSize + i] = b.mpData[i];
|
||||||
|
|
||||||
|
result.mpData[result.mSize] = '\0';
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Cat";
|
||||||
|
String b = "Mouse";
|
||||||
|
|
||||||
|
cout << a + b << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String() : String("") {}
|
||||||
|
String(const String& s) : String(s.cStr()) {}
|
||||||
|
|
||||||
|
String operator+(const String& b)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
result.mSize = mSize + b.mSize;
|
||||||
|
result.mCapacity = result.mSize + 1;
|
||||||
|
result.mpData = (char*)std::malloc(sizeof(char) * result.mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
result.mpData[i] = mpData[i];
|
||||||
|
|
||||||
|
for (size_t i = 0; i < b.mSize; ++i)
|
||||||
|
result.mpData[mSize + i] = b.mpData[i];
|
||||||
|
|
||||||
|
result.mpData[result.mSize] = '\0';
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
|
||||||
|
friend String operator+(const String& a, const String& b);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Cat";
|
||||||
|
String b = "Mouse";
|
||||||
|
|
||||||
|
cout << a + b << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,126 @@
|
||||||
|
/*
|
||||||
|
Оператор присваивания
|
||||||
|
|
||||||
|
Оператор присваивания можно сделать только в виде метода
|
||||||
|
Такой метод должен
|
||||||
|
- принимать один аргумент - это правый аргумент оператора присваивания,
|
||||||
|
- менять объект, вызвавший оператор (то есть левый аргумент оператора присваивания)
|
||||||
|
- возвращать ссылку на объект, вызвавший оператор (то есть объект слева от оператора присваивания)
|
||||||
|
|
||||||
|
|
||||||
|
Почему оператор присваивания должен возвращать ссылку на левый аргумент?
|
||||||
|
Чтобы оператор присваивания работал аналогично тому как работает оператор присваивания для обычных типов
|
||||||
|
|
||||||
|
Рассмотрим следующий пример:
|
||||||
|
|
||||||
|
int a, b, c;
|
||||||
|
a = b = c = 123; // все переменные станут равны 123, операторы выполняются справа налево
|
||||||
|
|
||||||
|
(a = 1) = 2; // a станет равной 2
|
||||||
|
|
||||||
|
|
||||||
|
Мы хотим, чтобы и такой код работал:
|
||||||
|
|
||||||
|
String a, b, c;
|
||||||
|
a = b = c = "Cat";
|
||||||
|
|
||||||
|
(a = "Dog") = "Mouse";
|
||||||
|
|
||||||
|
|
||||||
|
Прототип оператора присваивания как метода класса String должен выглядеть так:
|
||||||
|
|
||||||
|
String& operator=(const String& b)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String() : String("") {}
|
||||||
|
String(const String& s) : String(s.cStr()) {}
|
||||||
|
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
// Ваш код нужно написать здесь
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Cat";
|
||||||
|
String b = "Mouse";
|
||||||
|
String c;
|
||||||
|
|
||||||
|
a = b;
|
||||||
|
cout << a << endl;
|
||||||
|
|
||||||
|
a = b = c = "Elephant";
|
||||||
|
cout << a << endl;
|
||||||
|
cout << b << endl;
|
||||||
|
cout << c << endl;
|
||||||
|
|
||||||
|
(a = "Dog") = "Axolotl";
|
||||||
|
cout << a << endl;
|
||||||
|
|
||||||
|
a = a;
|
||||||
|
cout << a << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задание:
|
||||||
|
|
||||||
|
1) Написать оператор присваивания для строки String в виде метода класса String
|
||||||
|
|
||||||
|
Не забудьте учесть случай:
|
||||||
|
|
||||||
|
String a = "Cat";
|
||||||
|
a = a;
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,92 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String() : String("") {}
|
||||||
|
String(const String& s) : String(s.cStr()) {}
|
||||||
|
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
mCapacity = right.mCapacity;
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Cat";
|
||||||
|
String b = "Mouse";
|
||||||
|
String c;
|
||||||
|
|
||||||
|
a = b;
|
||||||
|
cout << a << endl;
|
||||||
|
|
||||||
|
a = b = c = "Elephant";
|
||||||
|
cout << a << endl;
|
||||||
|
cout << b << endl;
|
||||||
|
cout << c << endl;
|
||||||
|
|
||||||
|
(a = "Dog") = "Axolotl";
|
||||||
|
cout << a << endl;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,132 @@
|
||||||
|
/*
|
||||||
|
Оператор присваивания сложения +=
|
||||||
|
|
||||||
|
Очень похож на оператор присваивания, разница только в том, каким станет левый операнд после применения этого оператора
|
||||||
|
К левому операнду в этом случае должна прибавиться копия правого оператора
|
||||||
|
|
||||||
|
Если a = "Cat" , b = "Dog" , то после применения a += b строка a будет равна "CatDog"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Прототип оператора присваивания сложения как метода класса String должен выглядеть так:
|
||||||
|
|
||||||
|
String& operator+=(const String& b)
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String() : String("") {}
|
||||||
|
String(const String& s) : String(s.cStr()) {}
|
||||||
|
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
String operator+(const String& b)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
result.mSize = mSize + b.mSize;
|
||||||
|
result.mCapacity = result.mSize + 1;
|
||||||
|
result.mpData = (char*)std::malloc(sizeof(char) * result.mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
result.mpData[i] = mpData[i];
|
||||||
|
|
||||||
|
for (size_t i = 0; i < b.mSize; ++i)
|
||||||
|
result.mpData[mSize + i] = b.mpData[i];
|
||||||
|
|
||||||
|
result.mpData[result.mSize] = '\0';
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
mCapacity = right.mCapacity;
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
String& operator+=(const String& right)
|
||||||
|
{
|
||||||
|
// Ваш код нужно написать здесь
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Mouse";
|
||||||
|
String b = "Elephant";
|
||||||
|
|
||||||
|
b += a;
|
||||||
|
|
||||||
|
cout << b << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задание:
|
||||||
|
|
||||||
|
1) Написать оператор присваивания сложения для строки String в виде метода класса String
|
||||||
|
|
||||||
|
Подсказка: можно использовать уже написанные операторы, чтобы реализовать этот
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String() : String("") {}
|
||||||
|
String(const String& s) : String(s.cStr()) {}
|
||||||
|
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
String operator+(const String& b)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
|
||||||
|
result.mSize = mSize + b.mSize;
|
||||||
|
result.mCapacity = result.mSize + 1;
|
||||||
|
result.mpData = (char*)std::malloc(sizeof(char) * result.mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
result.mpData[i] = mpData[i];
|
||||||
|
|
||||||
|
for (size_t i = 0; i < b.mSize; ++i)
|
||||||
|
result.mpData[mSize + i] = b.mpData[i];
|
||||||
|
|
||||||
|
result.mpData[result.mSize] = '\0';
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
mCapacity = right.mCapacity;
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
String& operator+=(const String& right)
|
||||||
|
{
|
||||||
|
*this = *this + right;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Mouse";
|
||||||
|
String b = "Elephant";
|
||||||
|
|
||||||
|
b += a;
|
||||||
|
|
||||||
|
cout << b << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
По решению предыдущего занятия понятно, что операторы + = и += взаимосвязаны.
|
||||||
|
|
||||||
|
Если реализованы операторы + и = можно, используя их, реализовать оператор +=
|
||||||
|
Если реализованы операторы = и += можно, используя их, реализовать оператор +
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String() : String("") {}
|
||||||
|
String(const String& s) : String(s.cStr()) {}
|
||||||
|
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
mCapacity = right.mCapacity;
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator+=(const String& right)
|
||||||
|
{
|
||||||
|
if (mCapacity < mSize + right.mSize + 1)
|
||||||
|
{
|
||||||
|
mCapacity = mSize + right.mSize + 1;
|
||||||
|
char* pNewData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
pNewData[i] = mpData[i];
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = pNewData;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < right.mSize; ++i)
|
||||||
|
mpData[mSize + i] = right.mpData[i];
|
||||||
|
|
||||||
|
mSize += right.mSize;
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
String operator+(const String& b)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Mouse";
|
||||||
|
String b = "Elephant";
|
||||||
|
|
||||||
|
cout << a + b << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
1) Напишите оператор + , используя операторы = и +=
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,108 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String() : String("") {}
|
||||||
|
String(const String& s) : String(s.cStr()) {}
|
||||||
|
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
mCapacity = right.mCapacity;
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator+=(const String& right)
|
||||||
|
{
|
||||||
|
if (mCapacity < mSize + right.mSize + 1)
|
||||||
|
{
|
||||||
|
mCapacity = mSize + right.mSize + 1;
|
||||||
|
char* pNewData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
pNewData[i] = mpData[i];
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = pNewData;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < right.mSize; ++i)
|
||||||
|
mpData[mSize + i] = right.mpData[i];
|
||||||
|
|
||||||
|
mSize += right.mSize;
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
String operator+(const String& b)
|
||||||
|
{
|
||||||
|
String result = *this;
|
||||||
|
result += b;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Mouse";
|
||||||
|
String b = "Elephant";
|
||||||
|
|
||||||
|
cout << a + b << endl;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,120 @@
|
||||||
|
/*
|
||||||
|
Операторы сравнения == != > >= < <=
|
||||||
|
|
||||||
|
К строкам можно применять операторы сравнения.
|
||||||
|
|
||||||
|
Очевидно, когда строки равны: должны быть равны размеры строк (mSize) и все символы от 0 до mSize
|
||||||
|
При этом вместимость (mCapacity) у равных строк может отличаться
|
||||||
|
|
||||||
|
Как сравнивать строки на больше/меньше? В этом случае сравниваем лексикографически, то есть, по алфавиту.
|
||||||
|
То слово, которое находилось бы в орфографическом словаре позже и будет большим.
|
||||||
|
Например, "Cat" > "Camel" так как первые 2 буквы совпадают, а третья буква у слова Cat идёт дальше по алфавиту
|
||||||
|
|
||||||
|
|
||||||
|
Более точное сравнение такое: мы сравниваем посимвольно до первого несовпадающего символа
|
||||||
|
Если мы нашли первые несовпадающий символ и не дошли до конца в обоих строках, то та строка будет больше,
|
||||||
|
у которой этот символ больше.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String() : String("") {}
|
||||||
|
String(const String& s) : String(s.cStr()) {}
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
mCapacity = right.mCapacity;
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
cout << std::boolalpha;
|
||||||
|
|
||||||
|
String a = "Cat";
|
||||||
|
String b = "Camel";
|
||||||
|
|
||||||
|
cout << (a > b) << endl;
|
||||||
|
cout << (a < b) << endl;
|
||||||
|
cout << (a == b) << endl;
|
||||||
|
cout << (a == a) << endl;
|
||||||
|
|
||||||
|
|
||||||
|
String c = "Catharsis";
|
||||||
|
|
||||||
|
cout << (a > c) << endl;
|
||||||
|
cout << (a < c) << endl;
|
||||||
|
cout << (a == c) << endl;
|
||||||
|
cout << (a != c) << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
1) Напишите операторы == != > >= < <= для класса String
|
||||||
|
Подсказка: можно использовать уже написанные сравнения
|
||||||
|
Например, если вы написали оператор > , то очень просто написать оператор <= , используя оператор >
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,140 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String() : String("") {}
|
||||||
|
String(const String& s) : String(s.cStr()) {}
|
||||||
|
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
mCapacity = right.mCapacity;
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool operator==(const String& right) const
|
||||||
|
{
|
||||||
|
if (mSize != right.mSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (i < mSize && mpData[i] == right.mpData[i])
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return i == mSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const String& right) const
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return mpData[i] < right.mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<=(const String& right) const
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return mpData[i] <= right.mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const String& right) const
|
||||||
|
{
|
||||||
|
return !(*this == right);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator>(const String& right) const
|
||||||
|
{
|
||||||
|
return !(*this <= right);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator>=(const String& right) const
|
||||||
|
{
|
||||||
|
return !(*this < right);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
cout << std::boolalpha;
|
||||||
|
|
||||||
|
String a = "Cat";
|
||||||
|
String b = "Camel";
|
||||||
|
|
||||||
|
cout << (a > b) << endl;
|
||||||
|
cout << (a < b) << endl;
|
||||||
|
cout << (a == b) << endl;
|
||||||
|
cout << (a == a) << endl;
|
||||||
|
|
||||||
|
|
||||||
|
String c = "Catharsis";
|
||||||
|
|
||||||
|
cout << (a > c) << endl;
|
||||||
|
cout << (a < c) << endl;
|
||||||
|
cout << (a == c) << endl;
|
||||||
|
cout << (a != c) << endl;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,122 @@
|
||||||
|
/*
|
||||||
|
Операторы индексации []
|
||||||
|
|
||||||
|
Чтобы получить доступ к одному символу у строки в стиле C можно использовать оператор индексации (квадратные скобочки).
|
||||||
|
Хотелось бы иметь такую же возможность и для нашей строки.
|
||||||
|
|
||||||
|
Для этого можно перегрузить оператор индексации:
|
||||||
|
|
||||||
|
char& operator[](size_t i)
|
||||||
|
|
||||||
|
Этот оператор вызавется при взятии символа по индексу, например, если a это строка типа String,
|
||||||
|
|
||||||
|
a[i] будет восприниматься компилятором как a.operator[](i)
|
||||||
|
|
||||||
|
|
||||||
|
Оператор индексации должен возвращать ссылку на символ, чтобы можно было менять соответствующий символ
|
||||||
|
|
||||||
|
a[i] = 'A';
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String() : String("") {}
|
||||||
|
String(const String& s) : String(s.cStr()) {}
|
||||||
|
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
mCapacity = right.mCapacity;
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Cat";
|
||||||
|
|
||||||
|
cout << a[0] << endl;
|
||||||
|
cout << a[2] << endl;
|
||||||
|
cout << a[4] << endl;
|
||||||
|
|
||||||
|
|
||||||
|
cout << a.at(0) << endl;
|
||||||
|
cout << a.at(2) << endl;
|
||||||
|
cout << a.at(4) << endl;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
1) Напишите оператор индексации для класса String
|
||||||
|
|
||||||
|
|
||||||
|
2) Напишите метод at, который будет работать аналогично оператору индексации, только с тем отличием, что
|
||||||
|
если на вход приходит неправильный индекс (т. е. индекс >= mSize), то метод at должен печатать сообщение
|
||||||
|
об ошибке и завершать программу.
|
||||||
|
Для завершения программы используйте функцию std::exit(1) из библиотеки <cstdlib>.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,102 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String() : String("") {}
|
||||||
|
String(const String& s) : String(s.cStr()) {}
|
||||||
|
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
mCapacity = right.mCapacity;
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
char& operator[](size_t i)
|
||||||
|
{
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
char& at(size_t i)
|
||||||
|
{
|
||||||
|
if (i >= mSize)
|
||||||
|
{
|
||||||
|
cout << "Error! Index is out of bounds." << endl;
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Cat";
|
||||||
|
|
||||||
|
cout << a[0] << endl;
|
||||||
|
cout << a[2] << endl;
|
||||||
|
cout << a[4] << endl;
|
||||||
|
|
||||||
|
|
||||||
|
cout << a.at(0) << endl;
|
||||||
|
cout << a.at(2) << endl;
|
||||||
|
cout << a.at(4) << endl;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,145 @@
|
||||||
|
/*
|
||||||
|
Напишем ещё 2 очень полезных метода:
|
||||||
|
|
||||||
|
1) reserve - увеличивает вместимость строки, на вход методу передаётся новая вместмость
|
||||||
|
если новая вместимость меньше старой, то ничего не происходит (вместимость не уменьшается)
|
||||||
|
размер и содержимое строки не меняется
|
||||||
|
|
||||||
|
|
||||||
|
2) resize - изменяет размер строки, на вход методу передаётся новый размер
|
||||||
|
если новый размер меньше старого, то строка усекается
|
||||||
|
при необходимости увеличивает вместимость
|
||||||
|
|
||||||
|
Используя эти два метода можно немного упростить код для операторов сложения и присваивания.
|
||||||
|
Эти методы могут быть полезны и для программиста, который будет работать с нашей строкой, поэтому сделаем их публичными.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String() : String("") {}
|
||||||
|
String(const String& s) : String(s.cStr()) {}
|
||||||
|
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void reserve(size_t capacity)
|
||||||
|
{
|
||||||
|
if (capacity <= mCapacity)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mCapacity = capacity;
|
||||||
|
char* newData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
newData[i] = mpData[i];
|
||||||
|
newData[mSize] = '\0';
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = newData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void resize(size_t size)
|
||||||
|
{
|
||||||
|
reserve(size + 1);
|
||||||
|
mSize = size;
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
resize(mSize);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String operator+(const String& b)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
result.resize(mSize + b.mSize);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
result.mpData[i] = mpData[i];
|
||||||
|
|
||||||
|
for (size_t i = 0; i < b.mSize; ++i)
|
||||||
|
result.mpData[mSize + i] = b.mpData[i];
|
||||||
|
|
||||||
|
result.mpData[result.mSize] = '\0';
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Cat";
|
||||||
|
String b = "Dog";
|
||||||
|
|
||||||
|
cout << a.getCapacity() << endl;
|
||||||
|
a.reserve(10);
|
||||||
|
cout << a.getCapacity() << endl;
|
||||||
|
|
||||||
|
cout << a + b << endl;
|
||||||
|
|
||||||
|
|
||||||
|
String c = "Sapere Aude";
|
||||||
|
cout << c << endl;
|
||||||
|
|
||||||
|
c.resize(6);
|
||||||
|
cout << c << endl;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,134 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::cin, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String() : String("") {}
|
||||||
|
String(const String& s) : String(s.cStr()) {}
|
||||||
|
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void reserve(size_t capacity)
|
||||||
|
{
|
||||||
|
if (capacity <= mCapacity)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mCapacity = capacity;
|
||||||
|
char* newData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
newData[i] = mpData[i];
|
||||||
|
newData[mSize] = '\0';
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = newData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void resize(size_t size)
|
||||||
|
{
|
||||||
|
reserve(size + 1);
|
||||||
|
mSize = size;
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
resize(mSize);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String operator+(const String& b)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
result.resize(mSize + b.mSize);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
result.mpData[i] = mpData[i];
|
||||||
|
|
||||||
|
for (size_t i = 0; i < b.mSize; ++i)
|
||||||
|
result.mpData[mSize + i] = b.mpData[i];
|
||||||
|
|
||||||
|
result.mpData[result.mSize] = '\0';
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
char& operator[](size_t i)
|
||||||
|
{
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Cat";
|
||||||
|
String b = "Dog";
|
||||||
|
|
||||||
|
cout << a.getCapacity() << endl;
|
||||||
|
a.reserve(10);
|
||||||
|
cout << a.getCapacity() << endl;
|
||||||
|
|
||||||
|
cout << a + b << endl;
|
||||||
|
|
||||||
|
|
||||||
|
String c = "Sapere Aude";
|
||||||
|
cout << c << endl;
|
||||||
|
|
||||||
|
c.resize(6);
|
||||||
|
cout << c << endl;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,166 @@
|
||||||
|
/*
|
||||||
|
Считывание строки с экрана
|
||||||
|
|
||||||
|
Помимо удобной печати на экран с помощью объекта std::cout, хотелось бы добавить удобное считываие строки
|
||||||
|
с помощью объекта std::cin.
|
||||||
|
|
||||||
|
Для этого нужно перегрузить оператор >> с объектами типа std::istream и String, то есть написать функцию:
|
||||||
|
|
||||||
|
std::istream& operator>>(std::istream& in, String& str)
|
||||||
|
|
||||||
|
Эта функция должна считывать символы из стандартного входа и добавлять в строку
|
||||||
|
Основная проблема в том, что мы не знаем сколько символов нужно считать, поэтому нужно считывать
|
||||||
|
посимвольно и добавлять символы по одному в строку пока не встретим пробельный символ (' ' или '\n' или '\t')
|
||||||
|
|
||||||
|
Для упрощения программы можно написать дополнительные методы
|
||||||
|
|
||||||
|
void clear() - метод, который будет очищать строку
|
||||||
|
mSize = 0, mCapacity = 1, строка по адресу mpData равна "\0"
|
||||||
|
|
||||||
|
void addCharacter(char c) - добавляет символ в конец строки
|
||||||
|
если у строки не хватает вместимости, то удваивает вместимость.
|
||||||
|
|
||||||
|
|
||||||
|
Для того, чтобы считать символ из стандартного входа можно использовать метод get класса istream
|
||||||
|
Этот метод возвращает следующий символ из стандартного входа
|
||||||
|
|
||||||
|
char x = cin.get();
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::cin, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String() : String("") {}
|
||||||
|
String(const String& s) : String(s.cStr()) {}
|
||||||
|
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void reserve(size_t capacity)
|
||||||
|
{
|
||||||
|
if (capacity <= mCapacity)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mCapacity = capacity;
|
||||||
|
char* newData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
newData[i] = mpData[i];
|
||||||
|
newData[mSize] = '\0';
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = newData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void resize(size_t size)
|
||||||
|
{
|
||||||
|
reserve(size + 1);
|
||||||
|
mSize = size;
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
resize(mSize);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String operator+(const String& b)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
result.resize(mSize + b.mSize);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
result.mpData[i] = mpData[i];
|
||||||
|
|
||||||
|
for (size_t i = 0; i < b.mSize; ++i)
|
||||||
|
result.mpData[mSize + i] = b.mpData[i];
|
||||||
|
|
||||||
|
result.mpData[result.mSize] = '\0';
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
char& operator[](size_t i)
|
||||||
|
{
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a, b;
|
||||||
|
cin >> a >> b;
|
||||||
|
cout << a + b;
|
||||||
|
|
||||||
|
a.addCharacter('!');
|
||||||
|
cout << a << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
1) Напишите метод clear.
|
||||||
|
|
||||||
|
2) Напишите метод addCharacter.
|
||||||
|
|
||||||
|
3) Напишите перегруженный оператор << для считывания строки с экрана.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,158 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::cin, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String() : String("") {}
|
||||||
|
String(const String& s) : String(s.cStr()) {}
|
||||||
|
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void reserve(size_t capacity)
|
||||||
|
{
|
||||||
|
if (capacity <= mCapacity)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mCapacity = capacity;
|
||||||
|
char* newData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
newData[i] = mpData[i];
|
||||||
|
newData[mSize] = '\0';
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = newData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void resize(size_t size)
|
||||||
|
{
|
||||||
|
reserve(size + 1);
|
||||||
|
mSize = size;
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
resize(mSize);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String operator+(const String& b)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
result.resize(mSize + b.mSize);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
result.mpData[i] = mpData[i];
|
||||||
|
|
||||||
|
for (size_t i = 0; i < b.mSize; ++i)
|
||||||
|
result.mpData[mSize + i] = b.mpData[i];
|
||||||
|
|
||||||
|
result.mpData[result.mSize] = '\0';
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
char& operator[](size_t i)
|
||||||
|
{
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
|
||||||
|
mSize = 0;
|
||||||
|
mCapacity = 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
mpData[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void addCharacter(char c)
|
||||||
|
{
|
||||||
|
if (mSize + 1 == mCapacity)
|
||||||
|
reserve(2 * mCapacity);
|
||||||
|
|
||||||
|
mpData[mSize] = c;
|
||||||
|
resize(mSize + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, const String& s)
|
||||||
|
{
|
||||||
|
out << s.cStr();
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::istream& operator>>(std::istream& in, String& s)
|
||||||
|
{
|
||||||
|
s.clear();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
char x = in.get();
|
||||||
|
if (x == ' ' || x == '\n' || x == '\t')
|
||||||
|
break;
|
||||||
|
s.addCharacter(x);
|
||||||
|
}
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a, b;
|
||||||
|
cin >> a >> b;
|
||||||
|
cout << a + b << endl;
|
||||||
|
|
||||||
|
a.addCharacter('!');
|
||||||
|
cout << a << endl;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,262 @@
|
||||||
|
/*
|
||||||
|
Собираем все методы вместе. Получилась строка, которой можно удобно пользоваться и не задумываться о выделении памяти.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::cin, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String() : String("") {}
|
||||||
|
String(const String& s) : String(s.cStr()) {}
|
||||||
|
|
||||||
|
String(size_t n, char a)
|
||||||
|
{
|
||||||
|
mSize = n;
|
||||||
|
mCapacity = n + 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
mpData[i] = a;
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reserve(size_t capacity)
|
||||||
|
{
|
||||||
|
if (capacity <= mCapacity)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mCapacity = capacity;
|
||||||
|
char* newData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
newData[i] = mpData[i];
|
||||||
|
newData[mSize] = '\0';
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = newData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void resize(size_t size)
|
||||||
|
{
|
||||||
|
reserve(size + 1);
|
||||||
|
mSize = size;
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
resize(mSize);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String operator+(const String& b)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
result.resize(mSize + b.mSize);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
result.mpData[i] = mpData[i];
|
||||||
|
|
||||||
|
for (size_t i = 0; i < b.mSize; ++i)
|
||||||
|
result.mpData[mSize + i] = b.mpData[i];
|
||||||
|
|
||||||
|
result.mpData[result.mSize] = '\0';
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator+=(const String& right)
|
||||||
|
{
|
||||||
|
*this = *this + right;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const String& right) const
|
||||||
|
{
|
||||||
|
if (mSize != right.mSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (i < mSize && mpData[i] == right.mpData[i])
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return i == mSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const String& right) const
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return mpData[i] < right.mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<=(const String& right) const
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return mpData[i] <= right.mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const String& right) const
|
||||||
|
{
|
||||||
|
return !(*this == right);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator>(const String& right) const
|
||||||
|
{
|
||||||
|
return !(*this <= right);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator>=(const String& right) const
|
||||||
|
{
|
||||||
|
return !(*this < right);
|
||||||
|
}
|
||||||
|
|
||||||
|
char& operator[](size_t i)
|
||||||
|
{
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
char& at(size_t i)
|
||||||
|
{
|
||||||
|
if (i >= mSize)
|
||||||
|
{
|
||||||
|
cout << "Error! Index is out of bounds." << endl;
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
|
||||||
|
mSize = 0;
|
||||||
|
mCapacity = 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
mpData[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void addCharacter(char c)
|
||||||
|
{
|
||||||
|
if (mSize + 1 == mCapacity)
|
||||||
|
reserve(2 * mCapacity);
|
||||||
|
|
||||||
|
mpData[mSize] = c;
|
||||||
|
resize(mSize + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, const String& s)
|
||||||
|
{
|
||||||
|
out << s.cStr();
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::istream& operator>>(std::istream& in, String& s)
|
||||||
|
{
|
||||||
|
s.clear();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
char x = in.get();
|
||||||
|
if (x == ' ' || x == '\n' || x == '\t')
|
||||||
|
break;
|
||||||
|
s.addCharacter(x);
|
||||||
|
}
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Mouse";
|
||||||
|
String b;
|
||||||
|
cin >> b;
|
||||||
|
String c = b;
|
||||||
|
|
||||||
|
if (a + c == "MouseLion")
|
||||||
|
cout << "Yes" << endl;
|
||||||
|
else
|
||||||
|
cout << "No" << endl;
|
||||||
|
|
||||||
|
|
||||||
|
if (a > "Mice")
|
||||||
|
cout << "Yes" << endl;
|
||||||
|
else
|
||||||
|
cout << "No" << endl;
|
||||||
|
|
||||||
|
|
||||||
|
c[0] = 'P';
|
||||||
|
cout << c << endl;
|
||||||
|
|
||||||
|
c += a;
|
||||||
|
cout << c << endl;
|
||||||
|
|
||||||
|
c = c + String(10, 'q');
|
||||||
|
cout << c << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
|
||||||
|
1) Напищите программу, которая будет считывать слова (используйте cin) в бесконечном цикле и каждый
|
||||||
|
раз печатать сумму всех слов. Например, если пользователь ввёл Hello, то программа должна напечатать
|
||||||
|
Hello и запросить следующее слово. Если затем пользователь введёт World, то программа должна будет
|
||||||
|
напечатать HelloWorld и запросить следуещее слово и так далее.
|
||||||
|
Программа должна останавливаться если пользователь ввёл слово "quit".
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,233 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::cin, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String() : String("") {}
|
||||||
|
String(const String& s) : String(s.cStr()) {}
|
||||||
|
|
||||||
|
String(size_t n, char a)
|
||||||
|
{
|
||||||
|
mSize = n;
|
||||||
|
mCapacity = n + 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
mpData[i] = a;
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reserve(size_t capacity)
|
||||||
|
{
|
||||||
|
if (capacity <= mCapacity)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mCapacity = capacity;
|
||||||
|
char* newData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
newData[i] = mpData[i];
|
||||||
|
newData[mSize] = '\0';
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = newData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void resize(size_t size)
|
||||||
|
{
|
||||||
|
reserve(size + 1);
|
||||||
|
mSize = size;
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
resize(mSize);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String operator+(const String& b)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
result.resize(mSize + b.mSize);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
result.mpData[i] = mpData[i];
|
||||||
|
|
||||||
|
for (size_t i = 0; i < b.mSize; ++i)
|
||||||
|
result.mpData[mSize + i] = b.mpData[i];
|
||||||
|
|
||||||
|
result.mpData[result.mSize] = '\0';
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator+=(const String& right)
|
||||||
|
{
|
||||||
|
*this = *this + right;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const String& right) const
|
||||||
|
{
|
||||||
|
if (mSize != right.mSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (i < mSize && mpData[i] == right.mpData[i])
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return i == mSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const String& right) const
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return mpData[i] < right.mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<=(const String& right) const
|
||||||
|
{
|
||||||
|
size_t i = 0;
|
||||||
|
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return mpData[i] <= right.mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const String& right) const
|
||||||
|
{
|
||||||
|
return !(*this == right);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator>(const String& right) const
|
||||||
|
{
|
||||||
|
return !(*this <= right);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator>=(const String& right) const
|
||||||
|
{
|
||||||
|
return !(*this < right);
|
||||||
|
}
|
||||||
|
|
||||||
|
char& operator[](size_t i)
|
||||||
|
{
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
char& at(size_t i)
|
||||||
|
{
|
||||||
|
if (i >= mSize)
|
||||||
|
{
|
||||||
|
cout << "Error! Index is out of bounds." << endl;
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
|
||||||
|
mSize = 0;
|
||||||
|
mCapacity = 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
mpData[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void addCharacter(char c)
|
||||||
|
{
|
||||||
|
if (mSize + 1 == mCapacity)
|
||||||
|
reserve(2 * mCapacity);
|
||||||
|
|
||||||
|
mpData[mSize] = c;
|
||||||
|
resize(mSize + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, const String& s)
|
||||||
|
{
|
||||||
|
out << s.cStr();
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::istream& operator>>(std::istream& in, String& s)
|
||||||
|
{
|
||||||
|
s.clear();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
char x = in.get();
|
||||||
|
if (x == ' ' || x == '\n' || x == '\t')
|
||||||
|
break;
|
||||||
|
s.addCharacter(x);
|
||||||
|
}
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String all;
|
||||||
|
String nextWord;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
cin >> nextWord;
|
||||||
|
if (nextWord == "quit")
|
||||||
|
break;
|
||||||
|
|
||||||
|
all += nextWord;
|
||||||
|
cout << all << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,142 @@
|
||||||
|
/*
|
||||||
|
Рассмотрим при каких условиях происходит вызов того или иного метода.
|
||||||
|
|
||||||
|
Для этого будем использовать класс String, в котором была добавлена печать на экран для конструкторов,
|
||||||
|
деструктора и оператора присваивания.
|
||||||
|
Например, конструктор по умолчанию будет печатать Default Constructor и т. д.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
cout << "String Constructor from const char* (" << str << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; ++i)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String()
|
||||||
|
{
|
||||||
|
cout << "String Default Constructor" << endl;
|
||||||
|
mSize = 0;
|
||||||
|
mCapacity = 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char));
|
||||||
|
mpData[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String(const String& s)
|
||||||
|
{
|
||||||
|
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
mSize = s.mSize;
|
||||||
|
mCapacity = mSize + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
mpData[i] = s.mpData[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
cout << "String Destructor (" << mpData << ")" << endl;
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
mCapacity = right.mCapacity;
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
char& operator[](size_t i)
|
||||||
|
{
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Cat";
|
||||||
|
String b = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Какие методы вызовутся в строке
|
||||||
|
|
||||||
|
String a = "Cat";
|
||||||
|
|
||||||
|
Выберите один из вариантов:
|
||||||
|
|
||||||
|
а) Только конструктор из const char*
|
||||||
|
б) Только оператор присваивания
|
||||||
|
в) И конструктор из const char* и оператор присваивания
|
||||||
|
|
||||||
|
|
||||||
|
2) Какие методы вызовутся в строке
|
||||||
|
|
||||||
|
String b = a;
|
||||||
|
|
||||||
|
Выберите один из вариантов:
|
||||||
|
|
||||||
|
а) Только конструктор копирования
|
||||||
|
б) Только оператор присваивания
|
||||||
|
в) И конструктор копирования и оператор присваивания
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
3) Проверьте ваши догадки скомпилировав и запустив программу
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,121 @@
|
||||||
|
/*
|
||||||
|
Рассмотрим при каких условиях происходит вызов того или иного метода.
|
||||||
|
|
||||||
|
Для этого будем использовать класс String, в котором была добавлена печать на экран для конструкторов,
|
||||||
|
деструктора и оператора присваивания.
|
||||||
|
Например, конструктор по умолчанию будет печатать Default Constructor и т. д.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
cout << "String Constructor from const char* (" << str << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; ++i)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String()
|
||||||
|
{
|
||||||
|
cout << "String Default Constructor" << endl;
|
||||||
|
mSize = 0;
|
||||||
|
mCapacity = 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char));
|
||||||
|
mpData[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String(const String& s)
|
||||||
|
{
|
||||||
|
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
mSize = s.mSize;
|
||||||
|
mCapacity = mSize + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
mpData[i] = s.mpData[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
cout << "String Destructor (" << mpData << ")" << endl;
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
mCapacity = right.mCapacity;
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
char& operator[](size_t i)
|
||||||
|
{
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Cat";
|
||||||
|
String c;
|
||||||
|
c = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Какие методы класса String вызовутся в данной программе.
|
||||||
|
|
||||||
|
2) Проверьте ваши догадки, скомпилировав и запустив программу
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
/*
|
||||||
|
Решения:
|
||||||
|
|
||||||
|
1) String a = "Cat";
|
||||||
|
|
||||||
|
Будет вызван только конструктор из const char*
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
2) String b = a;
|
||||||
|
|
||||||
|
Будет вызван только конструктор копирования
|
||||||
|
|
||||||
|
Несмотря на то, что в этих выражениях присутствует символ = оператор присваивания в этих случаях не вызывается.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
3) String c;
|
||||||
|
c = a;
|
||||||
|
|
||||||
|
Будет вызван конструктор по умолчанию в строке String c;
|
||||||
|
А потом будет вызван оператор присваивания в строке c = a;
|
||||||
|
|
||||||
|
|
||||||
|
Получается символ = может использоваться для обозначения двух разных вещей: инициализации и присваивания.
|
||||||
|
|
||||||
|
|
||||||
|
String a = "Cat"; // Инициализация строкой "Cat" (вызов коструктора от const char*)
|
||||||
|
|
||||||
|
String b = a; // Инициализация объектом a (вызов коструктора копирования)
|
||||||
|
|
||||||
|
String c; // Инициализация по умолчанию (вызов конструктора по умолчанию)
|
||||||
|
c = a; // Присваивание (вызов метода operator=)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,135 @@
|
||||||
|
/*
|
||||||
|
Посмотрим какие особые методы вызываются при передаче объекта в функцию.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
cout << "String Constructor from const char* (" << str << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; ++i)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String()
|
||||||
|
{
|
||||||
|
cout << "String Default Constructor" << endl;
|
||||||
|
mSize = 0;
|
||||||
|
mCapacity = 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char));
|
||||||
|
mpData[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String(const String& s)
|
||||||
|
{
|
||||||
|
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
mSize = s.mSize;
|
||||||
|
mCapacity = mSize + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
mpData[i] = s.mpData[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
cout << "String Destructor (" << mpData << ")" << endl;
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
mCapacity = right.mCapacity;
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
char& operator[](size_t i)
|
||||||
|
{
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void print(String s)
|
||||||
|
{
|
||||||
|
cout << s << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Cat";
|
||||||
|
print(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Какие методы класса String вызовутся в данной программе.
|
||||||
|
|
||||||
|
|
||||||
|
2) Проверьте ваши догадки скомпилировав и запустив программу
|
||||||
|
|
||||||
|
|
||||||
|
3) Что если мы будем передавать объект String в функцию print не по значению, а по ссылке, то есть изменим
|
||||||
|
функцию print на следующую:
|
||||||
|
|
||||||
|
void print(const String& s)
|
||||||
|
{
|
||||||
|
cout << s << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Какие методы будут вызваны теперь?
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
Решения:
|
||||||
|
|
||||||
|
1) В случае:
|
||||||
|
|
||||||
|
void print(String s)
|
||||||
|
{
|
||||||
|
cout << s << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Cat";
|
||||||
|
print(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
Вызовутся следующие методы:
|
||||||
|
|
||||||
|
1) Конструктор строки из "Cat"
|
||||||
|
|
||||||
|
|
||||||
|
2) При передаче объекта в функцию по значению, он должен быть скопирован.
|
||||||
|
Соответственно при вызове print(a) объект a должен скопироваться в объект s функции print.
|
||||||
|
Для обычных типов вроде int тут бы произошло побайтовое копирование, но для классов вызывается конструктор копирования.
|
||||||
|
|
||||||
|
|
||||||
|
3) Внутри функции print объект s печатается на экран. Затем мы выходим из функции print и уничтожаем все локальные объекты этой функции.
|
||||||
|
Соответственно вызовется деструктор для объекта s.
|
||||||
|
|
||||||
|
|
||||||
|
4) Затем мы выходим из функции main и уничтожаем все объекты, локальные для функции main.
|
||||||
|
Соответственно вызовется деструктор для объекта a.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
3) В случае:
|
||||||
|
|
||||||
|
void print(const String& s)
|
||||||
|
{
|
||||||
|
cout << s << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Cat";
|
||||||
|
print(a);
|
||||||
|
}
|
||||||
|
|
||||||
|
Вызовутся следующие методы:
|
||||||
|
|
||||||
|
1) Конструктор строки из "Cat"
|
||||||
|
|
||||||
|
|
||||||
|
При передаче объекта в функцию по ссылке, этот объект в функцию не копируется.
|
||||||
|
Поэтому никаких конструкторов копирования не вызывается.
|
||||||
|
|
||||||
|
|
||||||
|
2) Деструктор для строки a из функии main.
|
||||||
|
|
||||||
|
|
||||||
|
Получается, что обычно передавать объекты в функции более эффективно по ссылке, а не по значению.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,131 @@
|
||||||
|
/*
|
||||||
|
Особые методы при передачах в функцию
|
||||||
|
|
||||||
|
Посмотрим какие особые методы вызываются при передаче объекта в функцию
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
cout << "String Constructor from const char* (" << str << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; ++i)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String()
|
||||||
|
{
|
||||||
|
cout << "String Default Constructor" << endl;
|
||||||
|
mSize = 0;
|
||||||
|
mCapacity = 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char));
|
||||||
|
mpData[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String(const String& s)
|
||||||
|
{
|
||||||
|
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
mSize = s.mSize;
|
||||||
|
mCapacity = mSize + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
mpData[i] = s.mpData[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
cout << "String Destructor (" << mpData << ")" << endl;
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
mCapacity = right.mCapacity;
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
char& operator[](size_t i)
|
||||||
|
{
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void changeFirstLetter(String s)
|
||||||
|
{
|
||||||
|
s[0] = 'B';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Cat";
|
||||||
|
cout << a << endl;
|
||||||
|
|
||||||
|
changeFirstLetter(a);
|
||||||
|
cout << a << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Какие методы класса String вызовутся в данной программе.
|
||||||
|
|
||||||
|
2) Проверьте ваши догадки скомпилировав и запустив программу
|
||||||
|
|
||||||
|
3) Функция changeFirstLetter должна была менять первую букву нашей строки на букву 'B', но это не происходит и
|
||||||
|
строка a после вызова changeFirstLetter(a) остаётся неизменной.
|
||||||
|
Почему это происходит и как изменить функцию changeFirstLetter чтобы она меняла первую букву переданной строки.
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,136 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
cout << "String Constructor from const char* (" << str << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; ++i)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String()
|
||||||
|
{
|
||||||
|
cout << "String Default Constructor" << endl;
|
||||||
|
mSize = 0;
|
||||||
|
mCapacity = 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char));
|
||||||
|
mpData[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String(const String& s)
|
||||||
|
{
|
||||||
|
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
mSize = s.mSize;
|
||||||
|
mCapacity = mSize + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
mpData[i] = s.mpData[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
cout << "String Destructor (" << mpData << ")" << endl;
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
mCapacity = right.mCapacity;
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
char& operator[](size_t i)
|
||||||
|
{
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void changeFirstLetter(String& s)
|
||||||
|
{
|
||||||
|
s[0] = 'B';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Cat";
|
||||||
|
cout << a << endl;
|
||||||
|
|
||||||
|
changeFirstLetter(a);
|
||||||
|
cout << a << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Решение:
|
||||||
|
|
||||||
|
В такую функцию:
|
||||||
|
|
||||||
|
void changeFirstLetter(String s)
|
||||||
|
{
|
||||||
|
s[0] = 'B';
|
||||||
|
}
|
||||||
|
|
||||||
|
строка передавалась по значению и, следовательно, происходило копирование этой строки в объект s функции changeFirstLetter.
|
||||||
|
Функция changeFirstLetter меняла первую букву копии нашей строки, но оригинальная строка не менялась.
|
||||||
|
|
||||||
|
|
||||||
|
Для того, чтобы функция changeFirstLetter меняла оригинальную строку ей нужно передавать объект не по значению, а по ссылке вот так:
|
||||||
|
|
||||||
|
void changeFirstLetter(String& s)
|
||||||
|
{
|
||||||
|
s[0] = 'B';
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,149 @@
|
||||||
|
/*
|
||||||
|
Различный синтаксис вызова конструкторов
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
cout << "String Constructor from const char* (" << str << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; ++i)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String()
|
||||||
|
{
|
||||||
|
cout << "String Default Constructor" << endl;
|
||||||
|
mSize = 0;
|
||||||
|
mCapacity = 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char));
|
||||||
|
mpData[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String(const String& s)
|
||||||
|
{
|
||||||
|
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
mSize = s.mSize;
|
||||||
|
mCapacity = mSize + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
mpData[i] = s.mpData[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
cout << "String Destructor (" << mpData << ")" << endl;
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
mCapacity = right.mCapacity;
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
char& operator[](size_t i)
|
||||||
|
{
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Cat";
|
||||||
|
|
||||||
|
String b = String("Dog");
|
||||||
|
|
||||||
|
String c("Mouse");
|
||||||
|
|
||||||
|
String d = {"Tiger"};
|
||||||
|
|
||||||
|
String e = String{"Axolotl"};
|
||||||
|
|
||||||
|
String f {"Lion"};
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Ввиду того, что язык C++ имеет длинную историю, на протяжении которой в язык добавлялись новые возможности,
|
||||||
|
в языке существует множество способов сделать одно и то же разными способами.
|
||||||
|
|
||||||
|
Один из ярких примеров этого является инициализация объекта. В этом примере создаются 6 строк. Синтаксис различается,
|
||||||
|
но в данном случае все эти строки по сути делают одно и то же: cоздают объект с помощью конструктора от const char*.
|
||||||
|
При этом не вызывается никаких конструкторов копирования или операторов присваивания.
|
||||||
|
|
||||||
|
В современном языке C++ предпочтительным способом инициализации является вариант f:
|
||||||
|
|
||||||
|
String f {"Lion"};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Что напечатает данная программа?
|
||||||
|
В каком порядке вызовутся конструкторы и в каком порядке вызовутся деструкторы?
|
||||||
|
|
||||||
|
2) Скомпилируйте программу и запустите, чтобы проверить ваши догадки.
|
||||||
|
|
||||||
|
3) Создайте 5 объектов типа String с помощью конструктора по умолчанию, используя разный синтаксис вызова конструктора.
|
||||||
|
|
||||||
|
4) Пусть есть объект x типа String:
|
||||||
|
|
||||||
|
String x = "Cat";
|
||||||
|
|
||||||
|
Создайте 6 объектов типа String с помощью конструктора копирования, используя разный синтаксис вызова конструктора.
|
||||||
|
Все новые объекты должны копировать объект x.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,124 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
cout << "String Constructor from const char* (" << str << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; ++i)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String()
|
||||||
|
{
|
||||||
|
cout << "String Default Constructor" << endl;
|
||||||
|
mSize = 0;
|
||||||
|
mCapacity = 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char));
|
||||||
|
mpData[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String(const String& s)
|
||||||
|
{
|
||||||
|
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
mSize = s.mSize;
|
||||||
|
mCapacity = mSize + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
mpData[i] = s.mpData[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
cout << "String Destructor (" << mpData << ")" << endl;
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
mCapacity = right.mCapacity;
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
char& operator[](size_t i)
|
||||||
|
{
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a;
|
||||||
|
|
||||||
|
String b = String();
|
||||||
|
|
||||||
|
// String c();
|
||||||
|
|
||||||
|
String d = {};
|
||||||
|
|
||||||
|
String e = String{};
|
||||||
|
|
||||||
|
String f {};
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Аналогично есть множество вариантов синтаксиса вызова конструктора по умолчанию.
|
||||||
|
|
||||||
|
Только такой вариант вызова конструктора не работает:
|
||||||
|
|
||||||
|
String c();
|
||||||
|
|
||||||
|
Потому что в этом случае компилятор считает, что это объявление функции по имени c, которая ничего не принимает и возвращает объект типа String.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,116 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
cout << "String Constructor from const char* (" << str << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; ++i)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String()
|
||||||
|
{
|
||||||
|
cout << "String Default Constructor" << endl;
|
||||||
|
mSize = 0;
|
||||||
|
mCapacity = 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char));
|
||||||
|
mpData[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String(const String& s)
|
||||||
|
{
|
||||||
|
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
mSize = s.mSize;
|
||||||
|
mCapacity = mSize + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
mpData[i] = s.mpData[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
cout << "String Destructor (" << mpData << ")" << endl;
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
mCapacity = right.mCapacity;
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
char& operator[](size_t i)
|
||||||
|
{
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String x = "Cat";
|
||||||
|
|
||||||
|
|
||||||
|
String a = x;
|
||||||
|
|
||||||
|
String b = String(x);
|
||||||
|
|
||||||
|
String c(x);
|
||||||
|
|
||||||
|
String d = {x};
|
||||||
|
|
||||||
|
String e = String{x};
|
||||||
|
|
||||||
|
String f {x};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,197 @@
|
||||||
|
/*
|
||||||
|
Особые методы
|
||||||
|
|
||||||
|
В прошлой части мы рассмотрели различные методы классов. Некоторые из этих методов называются особыми.
|
||||||
|
Они выделяются по сравнению с другими методами тем, что они будут создаваться автоматически даже если вы их не напишите.
|
||||||
|
К особым методам класса относятся:
|
||||||
|
|
||||||
|
|
||||||
|
1) Конструктор по умолчанию. То есть конструктор, который не принимает ни одного аргумента.
|
||||||
|
В случае со строкой String это контруктор:
|
||||||
|
|
||||||
|
String()
|
||||||
|
|
||||||
|
|
||||||
|
2) Конструктор копирования. То есть конструктор, который создаёт объект из другого объекта такого же типа, что и данный.
|
||||||
|
В случае со строкой String это контруктор:
|
||||||
|
|
||||||
|
String(const String& s)
|
||||||
|
|
||||||
|
|
||||||
|
3) Деструктор. Это метод, который вызывается при удалении объекта. В отличии от конструкторов, деструктор у объекта всегда один.
|
||||||
|
В случае со строкой String это:
|
||||||
|
|
||||||
|
~String()
|
||||||
|
|
||||||
|
|
||||||
|
4) Оператор присваивания. Это метод, который вызывается при присваивании одного метода класса String другому методу класса String.
|
||||||
|
В случае со строкой String это:
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
5,6) Есть ещё 2 особых метода, которые мы пройдём позже.
|
||||||
|
|
||||||
|
|
||||||
|
Все остальные методы, включаю другие конструкторы и перегруженные операторы, к особым методам не относятся.
|
||||||
|
То есть остальные методы не могут создаваться автоматически.
|
||||||
|
|
||||||
|
|
||||||
|
В этой части мы рассмотрим при каких условиях происходит вызов того или иного особого метода.
|
||||||
|
Для этого будем использовать класс String, в котором была добавлена печать на экран для каждого особого метода и для коструктора из const char*.
|
||||||
|
Например, конструктор по умолчанию будет печатать Default Constructor и т. д.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
cout << "String Constructor from const char* (" << str << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; ++i)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String()
|
||||||
|
{
|
||||||
|
cout << "String Default Constructor" << endl;
|
||||||
|
mSize = 0;
|
||||||
|
mCapacity = 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char));
|
||||||
|
mpData[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String(const String& s)
|
||||||
|
{
|
||||||
|
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
mSize = s.mSize;
|
||||||
|
mCapacity = mSize + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
mpData[i] = s.mpData[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
cout << "String Destructor (" << mpData << ")" << endl;
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
mCapacity = right.mCapacity;
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
char& operator[](size_t i)
|
||||||
|
{
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Book
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
String title;
|
||||||
|
int pages;
|
||||||
|
float price;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Book a = Book();
|
||||||
|
cout << a.title << " " << a.pages << " " << a.price << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
У класса Book есть 3 поля, одно из которых имеет тип String.
|
||||||
|
Но у класса Book не определён ни один метод. У него нет никаких конструкторов или перегруженных операторов.
|
||||||
|
|
||||||
|
Теперь посмотрим на код:
|
||||||
|
|
||||||
|
Book a = Book();
|
||||||
|
|
||||||
|
Тут мы создаём объект типа Book с помощью конструктора по умолчанию. Но у Book не написан конструктор по умолчанию!
|
||||||
|
Что же произойдёт в этом случае? Ошибка? Нет, на самом деле в этом случае конструктор будет создан автоматически. Вот такой:
|
||||||
|
|
||||||
|
Book() {}
|
||||||
|
|
||||||
|
Автоматически-сгенерированный конструктор по умолчанию ничего не делает.
|
||||||
|
Тем не менее, перед вызовом этого конструктора, компилятор должен вызвать конструктор по умолчанию для всех полей класса,
|
||||||
|
у которых есть конструктор по умолчанию.
|
||||||
|
В этом случае, при создании объекта класса Book с помощью конструктора по умолчанию, будет вызван конструктор по умолчанию класса String.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Аналогично, автоматически сгенерируется деструктор по умолчанию, вот такой:
|
||||||
|
|
||||||
|
~Book() {}
|
||||||
|
|
||||||
|
Он пустой, но нужно помнить, что после вызова деструктора класса, автоматически вызываются деструкторы для все его полей (у которых есть деструкторы)
|
||||||
|
В этом случае, после вызова деструктора класса Book вызовется деструктор класса String.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Скомпилируйте программу, запустите и убедитесь, что в этом примере вызываются
|
||||||
|
конструктор по умолчанию и деструктор класса String.
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,191 @@
|
||||||
|
/*
|
||||||
|
Особые методы
|
||||||
|
|
||||||
|
Проверим, что компилятор автоматически генерирует конструктор копирования и оператор присваивания.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
cout << "String Constructor from const char* (" << str << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; ++i)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String()
|
||||||
|
{
|
||||||
|
cout << "String Default Constructor" << endl;
|
||||||
|
mSize = 0;
|
||||||
|
mCapacity = 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char));
|
||||||
|
mpData[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String(const String& s)
|
||||||
|
{
|
||||||
|
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
mSize = s.mSize;
|
||||||
|
mCapacity = mSize + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
mpData[i] = s.mpData[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
cout << "String Destructor (" << mpData << ")" << endl;
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
mCapacity = right.mCapacity;
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
char& operator[](size_t i)
|
||||||
|
{
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Book
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
String title;
|
||||||
|
int pages;
|
||||||
|
float price;
|
||||||
|
};
|
||||||
|
|
||||||
|
void print(Book x)
|
||||||
|
{
|
||||||
|
cout << x.title << " " << x.pages << " " << x.price << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Book a;
|
||||||
|
|
||||||
|
a.title = "War and Peace";
|
||||||
|
a.pages = 1000;
|
||||||
|
a.price = 1100;
|
||||||
|
|
||||||
|
Book b;
|
||||||
|
b = a;
|
||||||
|
print(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Что напечатает данная программа?
|
||||||
|
|
||||||
|
Разберём код из функции main подробно:
|
||||||
|
|
||||||
|
1) Вызывается автоматически сгенерированный конструктор по умолчанию в строке:
|
||||||
|
|
||||||
|
Book a;
|
||||||
|
|
||||||
|
При этом перед вызовом этого конструктора вызовется и конструктор класса String поля title.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
2) Полям объекта a присваиваются некоторые значения:
|
||||||
|
|
||||||
|
a.title = "War and Peace";
|
||||||
|
a.pages = 1000;
|
||||||
|
a.price = 1100;
|
||||||
|
|
||||||
|
Интересно отметить, что строка a.title = "War and Peace" работает, несмотря на то, что слева от знака
|
||||||
|
присваивания стоит объект типа String, а справа от знака присваивания стоит объект типа const char[14].
|
||||||
|
Типы не совпадают, но это работает, так как у класса String есть конструктор от const char*.
|
||||||
|
Таким образом, сначала вызовется этот конструктор и создастся временный объект типа String, а потом
|
||||||
|
вызовется оператор присваивания между двумя объектами класса String.
|
||||||
|
После этого временный объект удалится и, соответственно, вызовется его деструктор.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
3) Вызывается автоматически сгенерированный конструктор по умолчанию в строке:
|
||||||
|
|
||||||
|
Book b;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
4) Вызывается автоматически сгенерированный перегруженный оператор присваивания в строке:
|
||||||
|
|
||||||
|
b = a;
|
||||||
|
|
||||||
|
Автоматически сгенерированный оператор присваивания применяет оператор присваивания для каждого поля.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
5) Передача в функцию print осуществляется по значению. Следовательно в строке
|
||||||
|
|
||||||
|
print(b);
|
||||||
|
|
||||||
|
объект b должен быть скопирован внутрь функции. Для этого должен быть вызван конструктор копирования.
|
||||||
|
Конструктор копирования у класса Book не написан, поэтому компилятор автоматически его сгенерирует.
|
||||||
|
|
||||||
|
Автоматически сгенерированный конструктор копирования копирует каждое поле в соответствующее поле нового объекта.
|
||||||
|
Если у поля есть конструктор копирования (как например у класса String), то вызывается конструктор копирования этого поля.
|
||||||
|
Если у поля нет конструктора копирования (как например у int или float), то поле просто копируется побайтово.
|
||||||
|
|
||||||
|
|
||||||
|
6) Выходим из функции print и вызываем деструктор для объекта x.
|
||||||
|
|
||||||
|
7) Выходим из функции main и вызываем деструкторы для объектов a и b.
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,148 @@
|
||||||
|
/*
|
||||||
|
Замечание по поводу автоматической генерации конструктора по умолчанию
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
cout << "String Constructor from const char* (" << str << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; ++i)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String()
|
||||||
|
{
|
||||||
|
cout << "String Default Constructor" << endl;
|
||||||
|
mSize = 0;
|
||||||
|
mCapacity = 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char));
|
||||||
|
mpData[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String(const String& s)
|
||||||
|
{
|
||||||
|
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
mSize = s.mSize;
|
||||||
|
mCapacity = mSize + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
mpData[i] = s.mpData[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
cout << "String Destructor (" << mpData << ")" << endl;
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
mCapacity = right.mCapacity;
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
char& operator[](size_t i)
|
||||||
|
{
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Book
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
String title;
|
||||||
|
int pages;
|
||||||
|
float price;
|
||||||
|
|
||||||
|
Book(const String& aTitle, int aPages, float aPrice)
|
||||||
|
{
|
||||||
|
title = aTitle;
|
||||||
|
pages = aPages;
|
||||||
|
price = aPrice;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Book a;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Конструктор по умолчанию не генерируется автоматически если у класса написан хотя бы один конструктор (любой).
|
||||||
|
Например, в этом пример у класса Book написан один конструктор:
|
||||||
|
|
||||||
|
Book(const String& aTitle, int aPages, float aPrice)
|
||||||
|
|
||||||
|
Поэтому в данном случае конструктор по умочанию автоматически генерироваться не будет.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
В строке Book a; должен быть вызван конструктор по умолчанию.
|
||||||
|
Но у класса Book такого конструктора нет и автоматически он не был создан. Поэтому эта строка приведёт к ошибке.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Но конструктор копирования, оператор присваивания и деструктор автоматически генерироваться будут.
|
||||||
|
|
||||||
|
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
Исправьте ошибку, написав конструктор по умолчанию самостоятельно.
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,164 @@
|
||||||
|
/*
|
||||||
|
Удалённые методы
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
cout << "String Constructor from const char* (" << str << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; str[i]; ++i)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String()
|
||||||
|
{
|
||||||
|
cout << "String Default Constructor" << endl;
|
||||||
|
mSize = 0;
|
||||||
|
mCapacity = 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char));
|
||||||
|
mpData[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String(const String& s)
|
||||||
|
{
|
||||||
|
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
mSize = s.mSize;
|
||||||
|
mCapacity = mSize + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
mpData[i] = s.mpData[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
cout << "String Destructor (" << mpData << ")" << endl;
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
mCapacity = right.mCapacity;
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
char& operator[](size_t i)
|
||||||
|
{
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class Book
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
String title;
|
||||||
|
int pages;
|
||||||
|
float price;
|
||||||
|
|
||||||
|
Book() {};
|
||||||
|
|
||||||
|
Book(const String& aTitle, int aPages, float aPrice)
|
||||||
|
{
|
||||||
|
title = aTitle;
|
||||||
|
pages = aPages;
|
||||||
|
price = aPrice;
|
||||||
|
}
|
||||||
|
|
||||||
|
Book(const Book& b) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Book a;
|
||||||
|
|
||||||
|
Book b = a;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Если же вы не хотите создавать какой-либо метод и не хотите чтобы он создавался автоматически,
|
||||||
|
то его можно удалить с помощью ключевого слова delete.
|
||||||
|
|
||||||
|
|
||||||
|
Например, в этом примере у класса Book удалён конструктор копирования вот так:
|
||||||
|
|
||||||
|
Book(const Book& b) = delete;
|
||||||
|
|
||||||
|
Это означает, что конструктор копирования не создастся автоматически.
|
||||||
|
Поэтому в строке:
|
||||||
|
|
||||||
|
Book b = a;
|
||||||
|
|
||||||
|
произойдёт ошибка компиляции.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Задача:
|
||||||
|
|
||||||
|
1) Можно ли передать объект класса с удалённым конструктором копирования в функцию по значению?
|
||||||
|
|
||||||
|
Например, если есть функция:
|
||||||
|
|
||||||
|
void print(Book b)
|
||||||
|
{
|
||||||
|
cout << b.title << " "<< b.pages << " " << b.price << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Можно ли туда передать что-нибудь?
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,188 @@
|
||||||
|
/*
|
||||||
|
Неявное приведение типа с помощью конструктора от одного параметра.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* s)
|
||||||
|
{
|
||||||
|
cout << "String Constructor from const char* (" << s << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (s[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; s[i]; ++i)
|
||||||
|
mpData[i] = s[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String()
|
||||||
|
{
|
||||||
|
cout << "String Default Constructor" << endl;
|
||||||
|
mSize = 0;
|
||||||
|
mCapacity = 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char));
|
||||||
|
mpData[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String(const String& s)
|
||||||
|
{
|
||||||
|
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
mSize = s.mSize;
|
||||||
|
mCapacity = mSize + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
mpData[i] = s.mpData[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
cout << "String Destructor (" << mpData << ")" << endl;
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
mCapacity = right.mCapacity;
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
char& operator[](size_t i)
|
||||||
|
{
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void print(String s)
|
||||||
|
{
|
||||||
|
cout << s << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a;
|
||||||
|
a = "Dog";
|
||||||
|
|
||||||
|
print("Mouse");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Одна из скрытых вещей, где используются конструкторы, это для неявного приведения типов.
|
||||||
|
|
||||||
|
Рассмотрим следующие строки:
|
||||||
|
|
||||||
|
String a;
|
||||||
|
a = "Dog";
|
||||||
|
|
||||||
|
Во второй строке должен вызваться оператор присваивания.
|
||||||
|
Слева от оператора присваивания стоит объект типа String, а справа от оператора присваивания стоит объект типа const char[4].
|
||||||
|
Поэтому должен вызваться метод operator=(const char* s) класса String. (при передаче в функцию массив автоматически конвертируется в указатель)
|
||||||
|
Но такого метода в классе String нет. Что же тогда будет сделано?
|
||||||
|
|
||||||
|
В этом случае будет сделано следующее:
|
||||||
|
|
||||||
|
1) Будет создан временный объект типа String с использованием конструтора String(const char* s).
|
||||||
|
2) Будет вызван оператор присваивания operator=(const String& s). Объекту a присвоится временный объект.
|
||||||
|
3) Временный объект будет уничтожен, при этом вызовется деструктор класса String.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Рассмотрим строку:
|
||||||
|
|
||||||
|
print("Mouse");
|
||||||
|
|
||||||
|
Функция print должна принимать объект типа String, но на вход ей приходит объект типа const char[6].
|
||||||
|
Что будет сделано в этом случае?
|
||||||
|
И в этом случае всё сработает, так как объект s функции print будет создан с помощью конструктора класса String от const char*.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Таким образом конструктор от одного аргумента автоматически используется для неявного приведения одного типа в другой.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Что если мы напишем конструктор класса String от числа типа int.
|
||||||
|
Этот конструктор будет принимать число n и создавать строку, состоящую из n символов 'a'
|
||||||
|
|
||||||
|
|
||||||
|
String(int n)
|
||||||
|
{
|
||||||
|
cout << "String Constructor from int (" << n << ")" << endl;
|
||||||
|
|
||||||
|
mSize = n;
|
||||||
|
mCapacity = mSize + 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
mpData[i] = 'a';
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Будет ли этот конструктор использоваться для неявного приведения чисел типа int в строки типа String?
|
||||||
|
Например, будет ли работать следующий код:
|
||||||
|
|
||||||
|
String b;
|
||||||
|
b = 5;
|
||||||
|
|
||||||
|
(b будет строкой состоящей из 5 символов 'a' ?)
|
||||||
|
|
||||||
|
|
||||||
|
print(10);
|
||||||
|
|
||||||
|
(напечатает строку, состоящую из 10 символов 'a')
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,147 @@
|
||||||
|
/*
|
||||||
|
Ключевое слово explicit.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
using std::cout, std::endl, std::size_t;
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
size_t mSize;
|
||||||
|
size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit String(const char* s)
|
||||||
|
{
|
||||||
|
cout << "String Constructor from const char* (" << s << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
while (s[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; s[i]; ++i)
|
||||||
|
mpData[i] = s[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit String(int n)
|
||||||
|
{
|
||||||
|
cout << "String Constructor from int (" << n << ")" << endl;
|
||||||
|
|
||||||
|
mSize = n;
|
||||||
|
mCapacity = mSize + 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
mpData[i] = 'a';
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String()
|
||||||
|
{
|
||||||
|
cout << "String Default Constructor" << endl;
|
||||||
|
mSize = 0;
|
||||||
|
mCapacity = 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char));
|
||||||
|
mpData[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String(const String& s)
|
||||||
|
{
|
||||||
|
cout << "String Copy Constructor (" << s.mpData << ")" << endl;
|
||||||
|
|
||||||
|
size_t i = 0;
|
||||||
|
mSize = s.mSize;
|
||||||
|
mCapacity = mSize + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < mSize; ++i)
|
||||||
|
mpData[i] = s.mpData[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
cout << "String Destructor (" << mpData << ")" << endl;
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
cout << "String Assignment Operator (" << right.mpData << ")" << endl;
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
mCapacity = right.mCapacity;
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = (char*)malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
char& operator[](size_t i)
|
||||||
|
{
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize() const {return mSize;}
|
||||||
|
size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const String& right)
|
||||||
|
{
|
||||||
|
left << right.cStr();
|
||||||
|
return left;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void print(String s)
|
||||||
|
{
|
||||||
|
cout << s << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a;
|
||||||
|
a = "Dog";
|
||||||
|
|
||||||
|
print("Mouse");
|
||||||
|
print(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Иногда всё-таки не хочется, чтобы конструкторы использовались для неявного приведения типов.
|
||||||
|
Ведь такое приведение типов может произойти там, где мы этого не хотим.
|
||||||
|
|
||||||
|
Чтобы конструктор не использовался для неявного приведения, его нужно пометить с помощью ключевого слова explicit.
|
||||||
|
В этом примере, конструкторы String(const char* s) и String(int n) помечены как explicit.
|
||||||
|
Поэтому эти конструкторы не будут использоваться для неявного приведения типов и код в функции main выдаст ошибку.
|
||||||
|
Но эти конструкторы всё равно можно вызывать явно, вот так:
|
||||||
|
|
||||||
|
String a;
|
||||||
|
a = String("Dog");
|
||||||
|
|
||||||
|
print(String("Mouse"));
|
||||||
|
print(String(10));
|
||||||
|
*/
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
Раздельная компиляция.
|
||||||
|
|
||||||
|
В этой части мы вынесем весь код, связанный с нашим классом Point в отдельные файлы.
|
||||||
|
А также скомпилируем отдельно код, относящийся к нашему классу Point.
|
||||||
|
|
||||||
|
Это будет проделано в следующий примерах, а пока тут просто лежит код
|
||||||
|
класса Point из предыдущих частей.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <cmath>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
struct Point
|
||||||
|
{
|
||||||
|
float x, y;
|
||||||
|
|
||||||
|
Point operator+(Point b) const
|
||||||
|
{
|
||||||
|
Point result = {x + b.x, y + b.y};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float norm() const
|
||||||
|
{
|
||||||
|
return std::sqrt(x * x + y * y);
|
||||||
|
}
|
||||||
|
|
||||||
|
Point operator*(float k) const
|
||||||
|
{
|
||||||
|
Point result = {k * x, k * y};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void normalize()
|
||||||
|
{
|
||||||
|
float normv = norm();
|
||||||
|
x /= normv;
|
||||||
|
y /= normv;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, Point a)
|
||||||
|
{
|
||||||
|
out << std::setprecision(2) << "(" << a.x << ", " << a.y << ")";
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Point a = {7.2, 3.1};
|
||||||
|
cout << a.norm() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
/*
|
||||||
|
Вынос определений методов вне класса.
|
||||||
|
|
||||||
|
Методы внутри класса можно только объявить, а определить их можно вне класса.
|
||||||
|
Например, метод norm объявлен внутри класса:
|
||||||
|
|
||||||
|
float norm() const;
|
||||||
|
|
||||||
|
а определён вне класса:
|
||||||
|
|
||||||
|
float Point::norm() const
|
||||||
|
{
|
||||||
|
return std::sqrt(x * x + y * y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Чтобы компилятор понимал к какому классу относится тот или иной метод,
|
||||||
|
к его имени вне класса нужно добавить название класса и два двоеточия.
|
||||||
|
Поэтому метод norm вне класса Point называется как Point::norm.
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <cmath>
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
struct Point
|
||||||
|
{
|
||||||
|
float x, y;
|
||||||
|
|
||||||
|
Point operator+(Point b) const;
|
||||||
|
float norm() const;
|
||||||
|
Point operator*(float k) const;
|
||||||
|
void normalize();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Point Point::operator+(Point b) const
|
||||||
|
{
|
||||||
|
Point result = {x + b.x, y + b.y};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Point::norm() const
|
||||||
|
{
|
||||||
|
return std::sqrt(x * x + y * y);
|
||||||
|
}
|
||||||
|
|
||||||
|
Point Point::operator*(float k) const
|
||||||
|
{
|
||||||
|
Point result = {k * x, k * y};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Point::normalize()
|
||||||
|
{
|
||||||
|
float normv = norm();
|
||||||
|
x /= normv;
|
||||||
|
y /= normv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, Point a)
|
||||||
|
{
|
||||||
|
out << std::setprecision(2) << "(" << a.x << ", " << a.y << ")";
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Point a = {7.2, 3.1};
|
||||||
|
cout << a.norm() << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
Перенос кода в заголовочный файл
|
||||||
|
|
||||||
|
В этом примере мы перенесли весь код, связанный с классом Point в отдельный файл point.hpp.
|
||||||
|
Файл point.hpp подключается к файлу main.cpp с помощью директивы #include в строке:
|
||||||
|
|
||||||
|
#include "point.hpp"
|
||||||
|
|
||||||
|
На самом деле директива #include делает очень простую вещь: она просто берёт всё содержимое
|
||||||
|
передаваемого ей файла и вставляет это содержимое на место директивы.
|
||||||
|
То есть в этом примере за место #include "point.hpp" подставится всё содержимое файла point.hpp.
|
||||||
|
|
||||||
|
Так как директива #include уже сама вставила файл point.hpp в файл main.cpp, то дополнительно
|
||||||
|
указывать файл point.hpp при компиляции не нужно. Скомпилировать этот пример можно так:
|
||||||
|
|
||||||
|
g++ main.cpp
|
||||||
|
|
||||||
|
|
||||||
|
Стандартные библиотеки типа iostream подключаются так же. То есть где-то в системе, в какой-то папке
|
||||||
|
хранится стандартная библиотека C++ и, соответственно, есть файл под название iostream (без расширения).
|
||||||
|
Этот файл и подставляется за место строки #include <iostream>.
|
||||||
|
Чтобы посмотреть в каких папках компилятор ищет файлы стандартной библиотеки можно скомпилировать программу так:
|
||||||
|
|
||||||
|
g++ -v main.cpp
|
||||||
|
|
||||||
|
Он напечатает множество информации о компиляции, в числе прочего пути где происходит поиск при исполнении #include.
|
||||||
|
Вы могли заметить, что стандартные библиотеки в директиве #include пишутся в треугольных скобочках, а нашу
|
||||||
|
библиотеку point.hpp мы написали в двойных кавычках. В чём разница между этими вариантами?
|
||||||
|
На самом деле разница лишь в том, в каких папках компилятор ищет данные файлы.
|
||||||
|
Если мы пишем библиотеку в треугольных скобках, то компилятор ищет её в папках стандартной библиотеки.
|
||||||
|
Если мы пишем библиотеку в кавычках, то компилятор ищет её в папках текущей директории.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Защита от двойного включения
|
||||||
|
|
||||||
|
Используя директивы #include, очень легко включить один и тот же файл 2 и более раз.
|
||||||
|
Например, в этом примере файл iostream включается 2 раза: один раз непосредственно в файле main.cpp, а второй раз
|
||||||
|
он включится после того, как включиться файл point.hpp. Внутри файла point.hpp тоже есть #include <iostream>.
|
||||||
|
Если не предпринимать никаких действий, то произойдёт ошибка, так как одинаковые функции и классы
|
||||||
|
будут повторяться в программе несколько раз.
|
||||||
|
|
||||||
|
Чтобы защититься от этой проблемы нужно в начале заголовочного файла написать директиву
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
Таким образом компилятор будет понимать, что вы не хотите включать файл более одного раза и включит только одну копию файла.
|
||||||
|
Эта директива была использовани и в файле point.hpp.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "point.hpp"
|
||||||
|
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Point a = {7.2, 3.1};
|
||||||
|
cout << a.norm() << endl;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
#pragma once
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
struct Point
|
||||||
|
{
|
||||||
|
float x, y;
|
||||||
|
|
||||||
|
Point operator+(Point b) const
|
||||||
|
{
|
||||||
|
Point result = {x + b.x, y + b.y};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float norm() const
|
||||||
|
{
|
||||||
|
return std::sqrt(x * x + y * y);
|
||||||
|
}
|
||||||
|
|
||||||
|
Point operator*(float k) const
|
||||||
|
{
|
||||||
|
Point result = {k * x, k * y};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void normalize()
|
||||||
|
{
|
||||||
|
float normv = norm();
|
||||||
|
x /= normv;
|
||||||
|
y /= normv;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, Point a)
|
||||||
|
{
|
||||||
|
out << std::setprecision(2) << "(" << a.x << ", " << a.y << ")";
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
/*
|
||||||
|
Всё что относится к классу Point мы перенесли в отдельный файл point.hpp.
|
||||||
|
А также мы разделили объявления и определения методов в файле point.hpp.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <cmath>
|
||||||
|
#include "point.hpp"
|
||||||
|
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Point a = {7.2, 3.1};
|
||||||
|
cout << a.norm() << endl;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
#pragma once
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
struct Point
|
||||||
|
{
|
||||||
|
float x, y;
|
||||||
|
|
||||||
|
Point operator+(Point b) const;
|
||||||
|
float norm() const;
|
||||||
|
Point operator*(float k) const;
|
||||||
|
void normalize();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Point Point::operator+(Point b) const
|
||||||
|
{
|
||||||
|
Point result = {x + b.x, y + b.y};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Point::norm() const
|
||||||
|
{
|
||||||
|
return std::sqrt(x * x + y * y);
|
||||||
|
}
|
||||||
|
|
||||||
|
Point Point::operator*(float k) const
|
||||||
|
{
|
||||||
|
Point result = {k * x, k * y};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Point::normalize()
|
||||||
|
{
|
||||||
|
float normv = norm();
|
||||||
|
x /= normv;
|
||||||
|
y /= normv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, Point a)
|
||||||
|
{
|
||||||
|
out << std::setprecision(2) << "(" << a.x << ", " << a.y << ")";
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
/*
|
||||||
|
Раздельная компиляция
|
||||||
|
|
||||||
|
Теперь мы разделим объявления и определения всех методов класса Point.
|
||||||
|
Все объявления класса Point поместим в файл point.hpp, а определения методов в файл point.cpp.
|
||||||
|
Таким образом у нас получилось 2 компилируемых файла: main.cpp и point.cpp и 1 заголовочный файл point.hpp.
|
||||||
|
|
||||||
|
При этом заголовочный файл point.hpp должен подключаться везде, где используется класс Point.
|
||||||
|
То есть в данном случае он должен подключаться и в файл main.cpp и в файл point.cpp.
|
||||||
|
|
||||||
|
|
||||||
|
Для компиляции программы нужно указать компилятору на все компилируемые файлы вот так:
|
||||||
|
|
||||||
|
g++ main.cpp point.cpp
|
||||||
|
|
||||||
|
Если это не сделать и скомпилировать только файл main.cpp, то возникнет ошибка undefined reference to norm().
|
||||||
|
Грубо говоря программа будет знать, что есть класс Point и знать его методы (так как это всё описано в point.hpp),
|
||||||
|
но любые попытки вызвать эти методы будут приводить к ошибке, так как они не были скомпилированы.
|
||||||
|
|
||||||
|
|
||||||
|
Преемущество раздельной компиляции заключается в том, что компилировать разные .cpp файлы можно поотдельности.
|
||||||
|
Представьте, что у вас огромный проект, содержащий тысячи файлов и миллионы строк кода. Такой проект может компилироваться часами.
|
||||||
|
Теперь вы сделали небольшое изменение в одном файле этого проекта. Если бы нельзя было бы компилировать файлы поотдельности,
|
||||||
|
то после любого изменения вам бы пришлось компилировать весь проект заново и ждать часы пока компиляция закончится.
|
||||||
|
К счастью, .cpp файлы можно компилировать поотдельности и, если вы сделали изменение в одном файле, то скомпилировать
|
||||||
|
потребуется только тот файл, который вы изменили.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "point.hpp"
|
||||||
|
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Point a = {7.2, 3.1};
|
||||||
|
cout << a.norm() << endl;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <cmath>
|
||||||
|
#include "point.hpp"
|
||||||
|
|
||||||
|
Point Point::operator+(Point b) const
|
||||||
|
{
|
||||||
|
Point result = {x + b.x, y + b.y};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Point::norm() const
|
||||||
|
{
|
||||||
|
return std::sqrt(x * x + y * y);
|
||||||
|
}
|
||||||
|
|
||||||
|
Point Point::operator*(float k) const
|
||||||
|
{
|
||||||
|
Point result = {k * x, k * y};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Point::normalize()
|
||||||
|
{
|
||||||
|
float normv = norm();
|
||||||
|
x /= normv;
|
||||||
|
y /= normv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, Point a)
|
||||||
|
{
|
||||||
|
out << std::setprecision(2) << "(" << a.x << ", " << a.y << ")";
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
#pragma once
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
struct Point
|
||||||
|
{
|
||||||
|
float x, y;
|
||||||
|
|
||||||
|
Point operator+(Point b) const;
|
||||||
|
float norm() const;
|
||||||
|
Point operator*(float k) const;
|
||||||
|
void normalize();
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, Point a);
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
/*
|
||||||
|
Пространства имён
|
||||||
|
|
||||||
|
|
||||||
|
Имя Point достаточно распространённое и есть очень большая вероятность того, что при подключении нескольких библиотек
|
||||||
|
в некоторых из них тоже будет класс с именем Point. Конечно, если ничего не предпринять, это приведёт к ошибке.
|
||||||
|
|
||||||
|
Чтобы избежать ошибок, связанных с конфликтами имён, положим весь код нашего класса Point в пространство имён mipt.
|
||||||
|
Для этого обернём наш код в файлах point.hpp и point.cpp
|
||||||
|
|
||||||
|
namespace mipt
|
||||||
|
{
|
||||||
|
...
|
||||||
|
}
|
||||||
|
|
||||||
|
Теперь наш класс Point будет лежать в пространстве имён mipt.
|
||||||
|
Для его использования вне пространства имён mipt нужно писать mipt::Point (ну либо использовать using mipt::Point;)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "point.hpp"
|
||||||
|
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
mipt::Point a = {7.2, 3.1};
|
||||||
|
cout << a.norm() << endl;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <cmath>
|
||||||
|
#include "point.hpp"
|
||||||
|
|
||||||
|
namespace mipt
|
||||||
|
{
|
||||||
|
|
||||||
|
Point Point::operator+(Point b) const
|
||||||
|
{
|
||||||
|
Point result = {x + b.x, y + b.y};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Point::norm() const
|
||||||
|
{
|
||||||
|
return std::sqrt(x * x + y * y);
|
||||||
|
}
|
||||||
|
|
||||||
|
Point Point::operator*(float k) const
|
||||||
|
{
|
||||||
|
Point result = {k * x, k * y};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Point::normalize()
|
||||||
|
{
|
||||||
|
float normv = norm();
|
||||||
|
x /= normv;
|
||||||
|
y /= normv;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, Point a)
|
||||||
|
{
|
||||||
|
out << std::setprecision(2) << "(" << a.x << ", " << a.y << ")";
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
#pragma once
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
|
namespace mipt
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Point
|
||||||
|
{
|
||||||
|
float x, y;
|
||||||
|
|
||||||
|
Point operator+(Point b) const;
|
||||||
|
float norm() const;
|
||||||
|
Point operator*(float k) const;
|
||||||
|
void normalize();
|
||||||
|
};
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, Point a);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,265 @@
|
||||||
|
/*
|
||||||
|
В данной программе содержится класс String, написанный нами в одной из предыдущих частей.
|
||||||
|
|
||||||
|
Задачи:
|
||||||
|
|
||||||
|
1) Вынесите класс String в отдельный заголовочный файл string.hpp и скомпилируйте программу.
|
||||||
|
|
||||||
|
|
||||||
|
2) Вынесите объявления методов класса String в заголовочный файл string.hpp, а определения
|
||||||
|
методов в компилируемый файл string.cpp. Скомпилируйте программу.
|
||||||
|
|
||||||
|
|
||||||
|
3) Вынесите объявления методов класса String в заголовочный файл string.hpp, а определения
|
||||||
|
методов в компилируемый файл string.cpp. А также поместите весь код класса String в пространство имён mipt.
|
||||||
|
Скомпилируйте программу.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::size_t mSize;
|
||||||
|
std::size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
std::size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; str[i]; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String() : String("") {}
|
||||||
|
String(const String& s) : String(s.cStr()) {}
|
||||||
|
|
||||||
|
String(std::size_t n, char a)
|
||||||
|
{
|
||||||
|
mSize = n;
|
||||||
|
mCapacity = n + 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < mSize; ++i)
|
||||||
|
mpData[i] = a;
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reserve(std::size_t capacity)
|
||||||
|
{
|
||||||
|
if (capacity <= mCapacity)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mCapacity = capacity;
|
||||||
|
char* newData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < mSize; ++i)
|
||||||
|
newData[i] = mpData[i];
|
||||||
|
newData[mSize] = '\0';
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = newData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void resize(std::size_t size)
|
||||||
|
{
|
||||||
|
reserve(size + 1);
|
||||||
|
mSize = size;
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
resize(mSize);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String operator+(const String& b)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
result.resize(mSize + b.mSize);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < mSize; ++i)
|
||||||
|
result.mpData[i] = mpData[i];
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < b.mSize; ++i)
|
||||||
|
result.mpData[mSize + i] = b.mpData[i];
|
||||||
|
|
||||||
|
result.mpData[result.mSize] = '\0';
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator+=(const String& right)
|
||||||
|
{
|
||||||
|
*this = *this + right;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const String& right) const
|
||||||
|
{
|
||||||
|
if (mSize != right.mSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::size_t i = 0;
|
||||||
|
while (i < mSize && mpData[i] == right.mpData[i])
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return i == mSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const String& right) const
|
||||||
|
{
|
||||||
|
std::size_t i = 0;
|
||||||
|
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return mpData[i] < right.mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<=(const String& right) const
|
||||||
|
{
|
||||||
|
std::size_t i = 0;
|
||||||
|
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return mpData[i] <= right.mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const String& right) const
|
||||||
|
{
|
||||||
|
return !(*this == right);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator>(const String& right) const
|
||||||
|
{
|
||||||
|
return !(*this <= right);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator>=(const String& right) const
|
||||||
|
{
|
||||||
|
return !(*this < right);
|
||||||
|
}
|
||||||
|
|
||||||
|
char& operator[](std::size_t i)
|
||||||
|
{
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
char& at(std::size_t i)
|
||||||
|
{
|
||||||
|
if (i >= mSize)
|
||||||
|
{
|
||||||
|
std::cout << "Error! Index is out of bounds." << std::endl;
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
|
||||||
|
mSize = 0;
|
||||||
|
mCapacity = 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
mpData[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void addCharacter(char c)
|
||||||
|
{
|
||||||
|
if (mSize + 1 == mCapacity)
|
||||||
|
reserve(2 * mCapacity);
|
||||||
|
|
||||||
|
mpData[mSize] = c;
|
||||||
|
resize(mSize + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::size_t getSize() const {return mSize;}
|
||||||
|
std::size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, const String& s)
|
||||||
|
{
|
||||||
|
out << s.cStr();
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::istream& operator>>(std::istream& in, String& s)
|
||||||
|
{
|
||||||
|
s.clear();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
char x = in.get();
|
||||||
|
if (x == ' ' || x == '\n' || x == '\t')
|
||||||
|
break;
|
||||||
|
s.addCharacter(x);
|
||||||
|
}
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Mouse";
|
||||||
|
String b;
|
||||||
|
std::cin >> b;
|
||||||
|
String c = b;
|
||||||
|
|
||||||
|
if (a + c == "MouseLion")
|
||||||
|
std::cout << "Yes" << std::endl;
|
||||||
|
else
|
||||||
|
std::cout << "No" << std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
if (a > "Mice")
|
||||||
|
std::cout << "Yes" << std::endl;
|
||||||
|
else
|
||||||
|
std::cout << "No" << std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
c[0] = 'P';
|
||||||
|
std::cout << c << std::endl;
|
||||||
|
|
||||||
|
c += a;
|
||||||
|
std::cout << c << std::endl;
|
||||||
|
|
||||||
|
c = c + String(10, 'q');
|
||||||
|
std::cout << c << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include "string.hpp"
|
||||||
|
|
||||||
|
using std::cout, std::cin, std::endl;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Mouse";
|
||||||
|
String b;
|
||||||
|
cin >> b;
|
||||||
|
String c = b;
|
||||||
|
|
||||||
|
if (a + c == "MouseLion")
|
||||||
|
cout << "Yes" << endl;
|
||||||
|
else
|
||||||
|
cout << "No" << endl;
|
||||||
|
|
||||||
|
|
||||||
|
if (a > "Mice")
|
||||||
|
cout << "Yes" << endl;
|
||||||
|
else
|
||||||
|
cout << "No" << endl;
|
||||||
|
|
||||||
|
|
||||||
|
c[0] = 'P';
|
||||||
|
cout << c << endl;
|
||||||
|
|
||||||
|
c += a;
|
||||||
|
cout << c << endl;
|
||||||
|
|
||||||
|
c = c + String(10, 'q');
|
||||||
|
cout << c << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,214 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::size_t mSize;
|
||||||
|
std::size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str)
|
||||||
|
{
|
||||||
|
std::size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; str[i]; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String() : String("") {}
|
||||||
|
String(const String& s) : String(s.cStr()) {}
|
||||||
|
|
||||||
|
String(std::size_t n, char a)
|
||||||
|
{
|
||||||
|
mSize = n;
|
||||||
|
mCapacity = n + 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < mSize; ++i)
|
||||||
|
mpData[i] = a;
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
~String()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void reserve(std::size_t capacity)
|
||||||
|
{
|
||||||
|
if (capacity <= mCapacity)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mCapacity = capacity;
|
||||||
|
char* newData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < mSize; ++i)
|
||||||
|
newData[i] = mpData[i];
|
||||||
|
newData[mSize] = '\0';
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = newData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void resize(std::size_t size)
|
||||||
|
{
|
||||||
|
reserve(size + 1);
|
||||||
|
mSize = size;
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String& operator=(const String& right)
|
||||||
|
{
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
resize(mSize);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String operator+(const String& b)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
result.resize(mSize + b.mSize);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < mSize; ++i)
|
||||||
|
result.mpData[i] = mpData[i];
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < b.mSize; ++i)
|
||||||
|
result.mpData[mSize + i] = b.mpData[i];
|
||||||
|
|
||||||
|
result.mpData[result.mSize] = '\0';
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
String& operator+=(const String& right)
|
||||||
|
{
|
||||||
|
*this = *this + right;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const String& right) const
|
||||||
|
{
|
||||||
|
if (mSize != right.mSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::size_t i = 0;
|
||||||
|
while (i < mSize && mpData[i] == right.mpData[i])
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return i == mSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<(const String& right) const
|
||||||
|
{
|
||||||
|
std::size_t i = 0;
|
||||||
|
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return mpData[i] < right.mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator<=(const String& right) const
|
||||||
|
{
|
||||||
|
std::size_t i = 0;
|
||||||
|
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return mpData[i] <= right.mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const String& right) const
|
||||||
|
{
|
||||||
|
return !(*this == right);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator>(const String& right) const
|
||||||
|
{
|
||||||
|
return !(*this <= right);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator>=(const String& right) const
|
||||||
|
{
|
||||||
|
return !(*this < right);
|
||||||
|
}
|
||||||
|
|
||||||
|
char& operator[](std::size_t i)
|
||||||
|
{
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
char& at(std::size_t i)
|
||||||
|
{
|
||||||
|
if (i >= mSize)
|
||||||
|
{
|
||||||
|
std::cout << "Error! Index is out of bounds." << std::endl;
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
|
||||||
|
mSize = 0;
|
||||||
|
mCapacity = 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
mpData[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void addCharacter(char c)
|
||||||
|
{
|
||||||
|
if (mSize + 1 == mCapacity)
|
||||||
|
reserve(2 * mCapacity);
|
||||||
|
|
||||||
|
mpData[mSize] = c;
|
||||||
|
resize(mSize + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::size_t getSize() const {return mSize;}
|
||||||
|
std::size_t getCapacity() const {return mCapacity;}
|
||||||
|
const char* cStr() const {return mpData;}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, const String& s)
|
||||||
|
{
|
||||||
|
out << s.cStr();
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::istream& operator>>(std::istream& in, String& s)
|
||||||
|
{
|
||||||
|
s.clear();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
char x = in.get();
|
||||||
|
if (x == ' ' || x == '\n' || x == '\t')
|
||||||
|
break;
|
||||||
|
s.addCharacter(x);
|
||||||
|
}
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
Компиляция:
|
||||||
|
|
||||||
|
g++ main.cpp string.cpp
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include "string.hpp"
|
||||||
|
using std::cout, std::cin, std::endl;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
String a = "Mouse";
|
||||||
|
String b;
|
||||||
|
cin >> b;
|
||||||
|
String c = b;
|
||||||
|
|
||||||
|
if (a + c == "MouseLion")
|
||||||
|
cout << "Yes" << endl;
|
||||||
|
else
|
||||||
|
cout << "No" << endl;
|
||||||
|
|
||||||
|
|
||||||
|
if (a > "Mice")
|
||||||
|
cout << "Yes" << endl;
|
||||||
|
else
|
||||||
|
cout << "No" << endl;
|
||||||
|
|
||||||
|
|
||||||
|
c[0] = 'P';
|
||||||
|
cout << c << endl;
|
||||||
|
|
||||||
|
c += a;
|
||||||
|
cout << c << endl;
|
||||||
|
|
||||||
|
c = c + String(10, 'q');
|
||||||
|
cout << c << endl;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,204 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include "string.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
String::String(const char* str)
|
||||||
|
{
|
||||||
|
std::size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; str[i]; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String() : String("") {}
|
||||||
|
String::String(const String& s) : String(s.cStr()) {}
|
||||||
|
|
||||||
|
String::String(std::size_t n, char a)
|
||||||
|
{
|
||||||
|
mSize = n;
|
||||||
|
mCapacity = n + 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < mSize; ++i)
|
||||||
|
mpData[i] = a;
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String::~String()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::reserve(std::size_t capacity)
|
||||||
|
{
|
||||||
|
if (capacity <= mCapacity)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mCapacity = capacity;
|
||||||
|
char* newData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < mSize; ++i)
|
||||||
|
newData[i] = mpData[i];
|
||||||
|
newData[mSize] = '\0';
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = newData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void String::resize(std::size_t size)
|
||||||
|
{
|
||||||
|
reserve(size + 1);
|
||||||
|
mSize = size;
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String& String::operator=(const String& right)
|
||||||
|
{
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
resize(mSize);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String String::operator+(const String& b)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
result.resize(mSize + b.mSize);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < mSize; ++i)
|
||||||
|
result.mpData[i] = mpData[i];
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < b.mSize; ++i)
|
||||||
|
result.mpData[mSize + i] = b.mpData[i];
|
||||||
|
|
||||||
|
result.mpData[result.mSize] = '\0';
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
String& String::operator+=(const String& right)
|
||||||
|
{
|
||||||
|
*this = *this + right;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool String::operator==(const String& right) const
|
||||||
|
{
|
||||||
|
if (mSize != right.mSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::size_t i = 0;
|
||||||
|
while (i < mSize && mpData[i] == right.mpData[i])
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return i == mSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool String::operator<(const String& right) const
|
||||||
|
{
|
||||||
|
std::size_t i = 0;
|
||||||
|
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return mpData[i] < right.mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool String::operator<=(const String& right) const
|
||||||
|
{
|
||||||
|
std::size_t i = 0;
|
||||||
|
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return mpData[i] <= right.mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool String::operator!=(const String& right) const
|
||||||
|
{
|
||||||
|
return !(*this == right);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool String::operator>(const String& right) const
|
||||||
|
{
|
||||||
|
return !(*this <= right);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool String::operator>=(const String& right) const
|
||||||
|
{
|
||||||
|
return !(*this < right);
|
||||||
|
}
|
||||||
|
|
||||||
|
char& String::operator[](std::size_t i)
|
||||||
|
{
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
char& String::at(std::size_t i)
|
||||||
|
{
|
||||||
|
if (i >= mSize)
|
||||||
|
{
|
||||||
|
std::cout << "Error! Index is out of bounds." << std::endl;
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::clear()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
|
||||||
|
mSize = 0;
|
||||||
|
mCapacity = 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
mpData[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::addCharacter(char c)
|
||||||
|
{
|
||||||
|
if (mSize + 1 == mCapacity)
|
||||||
|
reserve(2 * mCapacity);
|
||||||
|
|
||||||
|
mpData[mSize] = c;
|
||||||
|
resize(mSize + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::size_t String::getSize() const {return mSize;}
|
||||||
|
std::size_t String::getCapacity() const {return mCapacity;}
|
||||||
|
const char* String::cStr() const {return mpData;}
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, const String& s)
|
||||||
|
{
|
||||||
|
out << s.cStr();
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::istream& operator>>(std::istream& in, String& s)
|
||||||
|
{
|
||||||
|
s.clear();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
char x = in.get();
|
||||||
|
if (x == ' ' || x == '\n' || x == '\t')
|
||||||
|
break;
|
||||||
|
s.addCharacter(x);
|
||||||
|
}
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,51 @@
|
||||||
|
#pragma once
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::size_t mSize;
|
||||||
|
std::size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str);
|
||||||
|
|
||||||
|
String();
|
||||||
|
String(const String& s);
|
||||||
|
|
||||||
|
String(std::size_t n, char a);
|
||||||
|
~String();
|
||||||
|
|
||||||
|
void reserve(std::size_t capacity);
|
||||||
|
void resize(std::size_t size);
|
||||||
|
|
||||||
|
String& operator=(const String& right);
|
||||||
|
String operator+(const String& b);
|
||||||
|
String& operator+=(const String& right);
|
||||||
|
|
||||||
|
bool operator==(const String& right) const;
|
||||||
|
bool operator<(const String& right) const;
|
||||||
|
bool operator<=(const String& right) const;
|
||||||
|
bool operator!=(const String& right) const;
|
||||||
|
bool operator>(const String& right) const;
|
||||||
|
bool operator>=(const String& right) const;
|
||||||
|
|
||||||
|
char& operator[](std::size_t i);
|
||||||
|
char& at(std::size_t i);
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
void addCharacter(char c);
|
||||||
|
|
||||||
|
std::size_t getSize() const;
|
||||||
|
std::size_t getCapacity() const;
|
||||||
|
const char* cStr() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, const String& s);
|
||||||
|
std::istream& operator>>(std::istream& in, String& s);
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include "string.hpp"
|
||||||
|
using std::cout, std::cin, std::endl;
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
mipt::String a = "Mouse";
|
||||||
|
mipt::String b;
|
||||||
|
cin >> b;
|
||||||
|
mipt::String c = b;
|
||||||
|
|
||||||
|
if (a + c == "MouseLion")
|
||||||
|
cout << "Yes" << endl;
|
||||||
|
else
|
||||||
|
cout << "No" << endl;
|
||||||
|
|
||||||
|
|
||||||
|
if (a > "Mice")
|
||||||
|
cout << "Yes" << endl;
|
||||||
|
else
|
||||||
|
cout << "No" << endl;
|
||||||
|
|
||||||
|
|
||||||
|
c[0] = 'P';
|
||||||
|
cout << c << endl;
|
||||||
|
|
||||||
|
c += a;
|
||||||
|
cout << c << endl;
|
||||||
|
|
||||||
|
c = c + mipt::String(10, 'q');
|
||||||
|
cout << c << endl;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,207 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include "string.hpp"
|
||||||
|
|
||||||
|
namespace mipt {
|
||||||
|
|
||||||
|
String::String(const char* str)
|
||||||
|
{
|
||||||
|
std::size_t i = 0;
|
||||||
|
while (str[i] != '\0')
|
||||||
|
i++;
|
||||||
|
mSize = i;
|
||||||
|
mCapacity = i + 1;
|
||||||
|
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; str[i]; i++)
|
||||||
|
mpData[i] = str[i];
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String::String() : String("") {}
|
||||||
|
String::String(const String& s) : String(s.cStr()) {}
|
||||||
|
|
||||||
|
String::String(std::size_t n, char a)
|
||||||
|
{
|
||||||
|
mSize = n;
|
||||||
|
mCapacity = n + 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < mSize; ++i)
|
||||||
|
mpData[i] = a;
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
String::~String()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::reserve(std::size_t capacity)
|
||||||
|
{
|
||||||
|
if (capacity <= mCapacity)
|
||||||
|
return;
|
||||||
|
|
||||||
|
mCapacity = capacity;
|
||||||
|
char* newData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < mSize; ++i)
|
||||||
|
newData[i] = mpData[i];
|
||||||
|
newData[mSize] = '\0';
|
||||||
|
|
||||||
|
std::free(mpData);
|
||||||
|
mpData = newData;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void String::resize(std::size_t size)
|
||||||
|
{
|
||||||
|
reserve(size + 1);
|
||||||
|
mSize = size;
|
||||||
|
mpData[mSize] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String& String::operator=(const String& right)
|
||||||
|
{
|
||||||
|
if (this == &right)
|
||||||
|
return *this;
|
||||||
|
|
||||||
|
mSize = right.mSize;
|
||||||
|
resize(mSize);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i <= mSize; ++i)
|
||||||
|
mpData[i] = right.mpData[i];
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
String String::operator+(const String& b)
|
||||||
|
{
|
||||||
|
String result;
|
||||||
|
result.resize(mSize + b.mSize);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < mSize; ++i)
|
||||||
|
result.mpData[i] = mpData[i];
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < b.mSize; ++i)
|
||||||
|
result.mpData[mSize + i] = b.mpData[i];
|
||||||
|
|
||||||
|
result.mpData[result.mSize] = '\0';
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
String& String::operator+=(const String& right)
|
||||||
|
{
|
||||||
|
*this = *this + right;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool String::operator==(const String& right) const
|
||||||
|
{
|
||||||
|
if (mSize != right.mSize)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::size_t i = 0;
|
||||||
|
while (i < mSize && mpData[i] == right.mpData[i])
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return i == mSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool String::operator<(const String& right) const
|
||||||
|
{
|
||||||
|
std::size_t i = 0;
|
||||||
|
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return mpData[i] < right.mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool String::operator<=(const String& right) const
|
||||||
|
{
|
||||||
|
std::size_t i = 0;
|
||||||
|
while (i < mSize && i < right.mSize && mpData[i] == right.mpData[i])
|
||||||
|
i++;
|
||||||
|
|
||||||
|
return mpData[i] <= right.mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool String::operator!=(const String& right) const
|
||||||
|
{
|
||||||
|
return !(*this == right);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool String::operator>(const String& right) const
|
||||||
|
{
|
||||||
|
return !(*this <= right);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool String::operator>=(const String& right) const
|
||||||
|
{
|
||||||
|
return !(*this < right);
|
||||||
|
}
|
||||||
|
|
||||||
|
char& String::operator[](std::size_t i)
|
||||||
|
{
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
char& String::at(std::size_t i)
|
||||||
|
{
|
||||||
|
if (i >= mSize)
|
||||||
|
{
|
||||||
|
std::cout << "Error! Index is out of bounds." << std::endl;
|
||||||
|
std::exit(1);
|
||||||
|
}
|
||||||
|
return mpData[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::clear()
|
||||||
|
{
|
||||||
|
std::free(mpData);
|
||||||
|
|
||||||
|
mSize = 0;
|
||||||
|
mCapacity = 1;
|
||||||
|
mpData = (char*)std::malloc(sizeof(char) * mCapacity);
|
||||||
|
mpData[0] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void String::addCharacter(char c)
|
||||||
|
{
|
||||||
|
if (mSize + 1 == mCapacity)
|
||||||
|
reserve(2 * mCapacity);
|
||||||
|
|
||||||
|
mpData[mSize] = c;
|
||||||
|
resize(mSize + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::size_t String::getSize() const {return mSize;}
|
||||||
|
std::size_t String::getCapacity() const {return mCapacity;}
|
||||||
|
const char* String::cStr() const {return mpData;}
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, const String& s)
|
||||||
|
{
|
||||||
|
out << s.cStr();
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::istream& operator>>(std::istream& in, String& s)
|
||||||
|
{
|
||||||
|
s.clear();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
char x = in.get();
|
||||||
|
if (x == ' ' || x == '\n' || x == '\t')
|
||||||
|
break;
|
||||||
|
s.addCharacter(x);
|
||||||
|
}
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
#pragma once
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
namespace mipt {
|
||||||
|
|
||||||
|
class String
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::size_t mSize;
|
||||||
|
std::size_t mCapacity;
|
||||||
|
char* mpData;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
String(const char* str);
|
||||||
|
|
||||||
|
String();
|
||||||
|
String(const String& s);
|
||||||
|
|
||||||
|
String(std::size_t n, char a);
|
||||||
|
~String();
|
||||||
|
|
||||||
|
void reserve(std::size_t capacity);
|
||||||
|
void resize(std::size_t size);
|
||||||
|
|
||||||
|
String& operator=(const String& right);
|
||||||
|
String operator+(const String& b);
|
||||||
|
String& operator+=(const String& right);
|
||||||
|
|
||||||
|
bool operator==(const String& right) const;
|
||||||
|
bool operator<(const String& right) const;
|
||||||
|
bool operator<=(const String& right) const;
|
||||||
|
bool operator!=(const String& right) const;
|
||||||
|
bool operator>(const String& right) const;
|
||||||
|
bool operator>=(const String& right) const;
|
||||||
|
|
||||||
|
char& operator[](std::size_t i);
|
||||||
|
char& at(std::size_t i);
|
||||||
|
|
||||||
|
void clear();
|
||||||
|
void addCharacter(char c);
|
||||||
|
|
||||||
|
std::size_t getSize() const;
|
||||||
|
std::size_t getCapacity() const;
|
||||||
|
const char* cStr() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& out, const String& s);
|
||||||
|
std::istream& operator>>(std::istream& in, String& s);
|
||||||
|
|
||||||
|
}
|
||||||
38
seminar02_encapsulation/homework/code/0circle/circle.cpp
Normal file
38
seminar02_encapsulation/homework/code/0circle/circle.cpp
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <math.h>
|
||||||
|
#include "circle.h"
|
||||||
|
#include "point.h"
|
||||||
|
|
||||||
|
Circle::Circle(const Point& acenter, float aradius) {
|
||||||
|
mCenter = acenter;
|
||||||
|
mRadius = aradius;
|
||||||
|
}
|
||||||
|
Circle::Circle() {
|
||||||
|
mCenter = Point {0, 0};
|
||||||
|
mRadius = 1;
|
||||||
|
}
|
||||||
|
Circle::Circle(const Circle& circle) {
|
||||||
|
mCenter = circle.mCenter;
|
||||||
|
mRadius = circle.mRadius;
|
||||||
|
}
|
||||||
|
Point Circle::getCenter() const { return mCenter; }
|
||||||
|
float Circle::getRadius() const { return mRadius; }
|
||||||
|
|
||||||
|
void Circle::setCenter(const Point& p) {
|
||||||
|
mCenter = p;
|
||||||
|
}
|
||||||
|
void Circle::setRadius(float radius) {
|
||||||
|
mRadius = radius > 0 ? radius : 0;
|
||||||
|
}
|
||||||
|
float Circle::getArea() const {
|
||||||
|
return mRadius * mRadius * M_PI;
|
||||||
|
}
|
||||||
|
float Circle::getDistance(const Point& p) {
|
||||||
|
return mCenter.distance(p) - mRadius;
|
||||||
|
}
|
||||||
|
bool Circle::isColliding(const Circle& c) const {
|
||||||
|
return (mCenter.distance(c.getCenter()) - (mRadius + c.getRadius()) > 0) ? false : true;
|
||||||
|
}
|
||||||
|
void Circle::move(const Point& p) {
|
||||||
|
mCenter = mCenter + p;
|
||||||
|
}
|
||||||
23
seminar02_encapsulation/homework/code/0circle/circle.h
Normal file
23
seminar02_encapsulation/homework/code/0circle/circle.h
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
#include "point.h"
|
||||||
|
class Circle
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
Point mCenter;
|
||||||
|
float mRadius;
|
||||||
|
|
||||||
|
public:
|
||||||
|
Circle(const Point& acenter, float aradius);
|
||||||
|
Circle();
|
||||||
|
Circle(const Circle& circle);
|
||||||
|
Point getCenter() const;
|
||||||
|
float getRadius() const;
|
||||||
|
|
||||||
|
void setCenter(const Point& p);
|
||||||
|
void setRadius(float radius);
|
||||||
|
float getArea() const;
|
||||||
|
float getDistance(const Point& p);
|
||||||
|
bool isColliding(const Circle& c) const;
|
||||||
|
void move(const Point& p);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
44
seminar02_encapsulation/homework/code/0circle/main.cpp
Normal file
44
seminar02_encapsulation/homework/code/0circle/main.cpp
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include "point.h"
|
||||||
|
#include "circle.h"
|
||||||
|
|
||||||
|
using std::cout, std::endl;
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Point p = {7, -1};
|
||||||
|
Point q = {-4, 2};
|
||||||
|
cout << "Point p = " << p << endl;
|
||||||
|
cout << "Point q = " << q << endl;
|
||||||
|
cout << "p + q = " << p + q << endl;
|
||||||
|
|
||||||
|
|
||||||
|
Circle a {{4, 1}, 3};
|
||||||
|
Circle b;
|
||||||
|
// b = a;
|
||||||
|
|
||||||
|
cout << "Circle a: center: " << a.getCenter() << " radius: " << a.getRadius() << endl;
|
||||||
|
cout << "Circle b: center: " << b.getCenter() << " radius: " << b.getRadius() << endl;
|
||||||
|
|
||||||
|
cout << "Area of a = " << a.getArea() << endl;
|
||||||
|
cout << "Distance from point p to circle a = " << a.getDistance(p) << endl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cout << "Collisions:" << endl;
|
||||||
|
if (a.isColliding(b))
|
||||||
|
cout << "Yes, a is colliding b" << endl;
|
||||||
|
else
|
||||||
|
cout << "No, a isn't colliding b" << endl;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
cout << "Moving b by {1, 1}:" << endl;
|
||||||
|
b.move({1, 1});
|
||||||
|
if (a.isColliding(b))
|
||||||
|
cout << "Yes, a is colliding b" << endl;
|
||||||
|
else
|
||||||
|
cout << "No, a isn't colliding b" << endl;
|
||||||
|
|
||||||
|
}
|
||||||
82
seminar02_encapsulation/homework/code/0circle/point.cpp
Normal file
82
seminar02_encapsulation/homework/code/0circle/point.cpp
Normal file
|
|
@ -0,0 +1,82 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include "point.h"
|
||||||
|
|
||||||
|
|
||||||
|
Point::Point(float x, float y)
|
||||||
|
{
|
||||||
|
mx = x;
|
||||||
|
my = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
Point::Point()
|
||||||
|
{
|
||||||
|
mx = 0;
|
||||||
|
my = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
float Point::getX() const
|
||||||
|
{
|
||||||
|
return mx;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Point::getY() const
|
||||||
|
{
|
||||||
|
return my;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Point::setX(float x)
|
||||||
|
{
|
||||||
|
mx = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Point::setY(float y)
|
||||||
|
{
|
||||||
|
my = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Point::norm() const
|
||||||
|
{
|
||||||
|
return std::sqrt(mx * mx + my * my);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Point::normalize()
|
||||||
|
{
|
||||||
|
float pnorm = norm();
|
||||||
|
mx /= pnorm;
|
||||||
|
my /= pnorm;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Point::distance(const Point& p) const
|
||||||
|
{
|
||||||
|
return std::sqrt((p.mx - mx) * (p.mx - mx) + (p.my - my) * (p.my - my));
|
||||||
|
}
|
||||||
|
|
||||||
|
Point Point::operator+(const Point& right) const
|
||||||
|
{
|
||||||
|
Point result = {mx + right.mx, my + right.my};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Point Point::operator*(float a) const
|
||||||
|
{
|
||||||
|
Point result = {a * mx, a * my};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Point operator*(float a, const Point& p)
|
||||||
|
{
|
||||||
|
Point result = {a * p.mx, a * p.my};
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& left, const Point& right)
|
||||||
|
{
|
||||||
|
left << "(" << right.mx << ", " << right.my << ")";
|
||||||
|
return left;
|
||||||
|
}
|
||||||
37
seminar02_encapsulation/homework/code/0circle/point.h
Normal file
37
seminar02_encapsulation/homework/code/0circle/point.h
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/*
|
||||||
|
Поля x и y сделаны приватными
|
||||||
|
Конкретно для этого класса их можно было сделать публичными
|
||||||
|
Так как пользователь всё-равно будет иметь доступ без ограничений к этим полям через геттеры и сеттеры
|
||||||
|
Но они сделаны приватными для образовательных целей
|
||||||
|
*/
|
||||||
|
|
||||||
|
class Point
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
float mx, my;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Point(float x, float y);
|
||||||
|
Point();
|
||||||
|
|
||||||
|
float getX() const;
|
||||||
|
float getY() const;
|
||||||
|
void setX(float x);
|
||||||
|
void setY(float y);
|
||||||
|
|
||||||
|
void normalize();
|
||||||
|
float distance(const Point& p) const;
|
||||||
|
float norm() const;
|
||||||
|
Point operator+(const Point& right) const;
|
||||||
|
Point operator*(float a) const;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
friend Point operator*(float a, const Point& p);
|
||||||
|
friend std::ostream& operator<<(std::ostream& left, const Point& right);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
307
seminar02_encapsulation/homework/code/1number/number.cpp
Normal file
307
seminar02_encapsulation/homework/code/1number/number.cpp
Normal file
|
|
@ -0,0 +1,307 @@
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstring>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Класс Number -- класс положительных больших чисел
|
||||||
|
|
||||||
|
Большое число будет храниться в динамическом массиве data
|
||||||
|
Каждый элемент этого массива содержит разряд числа в 100-ричной системе счисления
|
||||||
|
(так как base = 100)
|
||||||
|
По сути, каждый элемент data хранит две цифры числа в десятичной записи
|
||||||
|
|
||||||
|
Значение 100 для системы счисления выбрано как компромис между
|
||||||
|
эффективностью и удобством написания программы.
|
||||||
|
Если выбрать значения базы 10 - то программа будет не так эффективна по памяти
|
||||||
|
Если выбрать значения базы 256 (максимально эффективное использование памяти для типа char),
|
||||||
|
то алгоритм печати на экран сильно усложнится
|
||||||
|
В качестве альтернативы, можно было выбрать базу 1e9,
|
||||||
|
изменив при этом тип элементов c char на int
|
||||||
|
|
||||||
|
capacity - размер массива data
|
||||||
|
size - сколько ячеек занимет число в массиве data
|
||||||
|
size <= capacity
|
||||||
|
|
||||||
|
Для удобства разряды числа хранятся в обратном порядке
|
||||||
|
Например, число 12345678 соответствует массиву
|
||||||
|
data = {78, 56, 34, 12}
|
||||||
|
(это упрощает многие алгоритмы с такими числами)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
class Number
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
static const int base = 100;
|
||||||
|
std::size_t size;
|
||||||
|
std::size_t capacity;
|
||||||
|
char* data;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Number(int a)
|
||||||
|
{
|
||||||
|
#ifdef _DEBUG_CONSTRUCTOR
|
||||||
|
std::cout << "(Number constructor " << a << " -> ";
|
||||||
|
#endif
|
||||||
|
// Находим размер необходимой памяти под это число
|
||||||
|
int temp = a;
|
||||||
|
capacity = 0;
|
||||||
|
while (temp != 0)
|
||||||
|
{
|
||||||
|
temp /= base;
|
||||||
|
capacity += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Отдельно обрабатываем случай, когда число равно 0
|
||||||
|
if (capacity == 0)
|
||||||
|
capacity = 1;
|
||||||
|
|
||||||
|
// Выделяем память и записывем число a в массив data
|
||||||
|
// Например, число 12345678 представится в виде массива [78, 56, 34, 12]
|
||||||
|
|
||||||
|
data = new char[capacity];
|
||||||
|
|
||||||
|
for (int i = 0; i < capacity; ++i)
|
||||||
|
{
|
||||||
|
data[i] = a % base;
|
||||||
|
a /= base;
|
||||||
|
}
|
||||||
|
|
||||||
|
// В данном случае размер будет равен вместимости
|
||||||
|
size = capacity;
|
||||||
|
#ifdef _DEBUG_CONSTRUCTOR
|
||||||
|
std::cout << *this << ")" << std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
// Конструктор по умолчанию
|
||||||
|
Number() : Number(0) {}
|
||||||
|
// Конструктор копирования
|
||||||
|
Number(const Number& n) {
|
||||||
|
size = n.size;
|
||||||
|
capacity = n.capacity;
|
||||||
|
data = new char[capacity];
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
data[i] = n.data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Number(const char* str) {
|
||||||
|
int len = std::strlen(str);
|
||||||
|
size = (len + len % 2) / 2;
|
||||||
|
capacity = size;
|
||||||
|
data = new char[capacity];
|
||||||
|
char buf[2];
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
buf[1] = str[len - 2 * i - 1];
|
||||||
|
if (len - 2 * i - 1 > 0) {
|
||||||
|
buf[0] = str[len - 2 * i - 2];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
buf[0] = '0';
|
||||||
|
}
|
||||||
|
data[i] = std::stoi(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
~Number()
|
||||||
|
{
|
||||||
|
delete [] data;
|
||||||
|
}
|
||||||
|
Number& operator=(const Number& right) {
|
||||||
|
capacity = right.capacity;
|
||||||
|
size = right.size;
|
||||||
|
data = new char[capacity];
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
data[i] = right.data[i];
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Number operator+(const Number& a) {
|
||||||
|
Number result;
|
||||||
|
int i;
|
||||||
|
char carry = 0;
|
||||||
|
int max_size = size > a.size ? size : a.size;
|
||||||
|
|
||||||
|
result.capacity = max_size + 1;
|
||||||
|
result.data = new char[capacity];
|
||||||
|
|
||||||
|
for (i = 0; i < max_size; ++i) {
|
||||||
|
result.data[i] = (data[i] + a.data[i] + carry) % base;
|
||||||
|
carry = (data[i] + a.data[i] + carry) / base;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (carry) {
|
||||||
|
result.data[i] = carry;
|
||||||
|
result.size = max_size + 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.size = max_size;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
void operator+=(const Number& a) {
|
||||||
|
*this = *this + a;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEven() const {
|
||||||
|
if (data[0] % 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Number operator*(const Number& right) const {
|
||||||
|
#ifdef _DEBUG_MUL
|
||||||
|
std::cout << "arg1=" << *this << "(capacity=" << capacity << ",size=" << size << ")" << " " << "arg2=" << right << "(capacity=" << right.capacity << ",size=" << right.size << ")"<< std::endl;
|
||||||
|
#endif
|
||||||
|
int i, j;
|
||||||
|
int temp;
|
||||||
|
Number result;
|
||||||
|
|
||||||
|
result.capacity = capacity + right.capacity;
|
||||||
|
int *carry = (int*)std::calloc(result.capacity, sizeof(int));
|
||||||
|
|
||||||
|
result.data = (char*)calloc(result.capacity, sizeof(char));
|
||||||
|
#ifdef _DEBUG_MUL
|
||||||
|
std::cout << "carry:[" << carry[0];
|
||||||
|
for (int k = 1; k < result.capacity; ++k) {
|
||||||
|
std::cout << "," << carry[k];
|
||||||
|
}
|
||||||
|
std::cout << "]" << std::endl;
|
||||||
|
#endif
|
||||||
|
for (i = 0; i < size; ++i) {
|
||||||
|
for (j = 0; j < right.size; ++j) {
|
||||||
|
#ifdef _DEBUG_MUL
|
||||||
|
std::cout << i + j << ":" << static_cast<int>(result.data[i + j]) << " + " << static_cast<int>(data[i]) << " * " << static_cast<int>(right.data[j]) << " + " << carry[i+j] << std::endl;
|
||||||
|
#endif
|
||||||
|
temp = (result.data[i + j] + data[i] * right.data[j] + carry[i + j]);
|
||||||
|
result.data[i + j] = temp % base;
|
||||||
|
carry[i + j + 1] += temp / base;
|
||||||
|
carry[i + j] = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef _DEBUG_MUL
|
||||||
|
std::cout << "result before applying carry:" << result << std::endl;
|
||||||
|
std::cout << "carry:[" << carry[0];
|
||||||
|
for (int k = 1; k < result.capacity; ++k) {
|
||||||
|
std::cout << "," << carry[k];
|
||||||
|
}
|
||||||
|
std::cout << "]" << std::endl;
|
||||||
|
#endif
|
||||||
|
if (carry[i + j - 1]) {
|
||||||
|
result.data[i + j - 1] = carry[i + j - 1];
|
||||||
|
result.size = i + j;
|
||||||
|
carry[i + j - 1] = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result.size = i + j - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _DEBUG_MUL
|
||||||
|
std::cout << "before correcting capacity, result=" << result << std::endl;
|
||||||
|
#endif
|
||||||
|
// correcting capacity
|
||||||
|
/*char* temp_data = (char *)calloc(result.size, sizeof(char));
|
||||||
|
for (i = 0; i < result.size; ++i) {
|
||||||
|
temp_data[i] = result.data[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
free(result.data);
|
||||||
|
result.capacity = result.size;
|
||||||
|
result.data = (char*)calloc(result.size,sizeof(char));
|
||||||
|
for (i = 0; i < result.size; ++i) {
|
||||||
|
result.data[i] = temp_data[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
free(temp_data);*/
|
||||||
|
free(carry);
|
||||||
|
#ifdef _DEBUG_MUL
|
||||||
|
std::cout << "return value=" << result << "(capacity=" << result.capacity << ",size=" << result.size << ")" << std::endl << "======" << std::endl;
|
||||||
|
#endif
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
void operator*=(const Number& a) {
|
||||||
|
*this = *this * a;
|
||||||
|
}
|
||||||
|
|
||||||
|
friend std::ostream& operator<<(std::ostream& stream, const Number& right);
|
||||||
|
friend int main();
|
||||||
|
friend Number factorial(int n);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::ostream& operator<<(std::ostream& stream, const Number& right)
|
||||||
|
{
|
||||||
|
#ifdef _DEBUG_COUT
|
||||||
|
stream << "[";
|
||||||
|
for (std::size_t i = 0; i < right.size; ++i) {
|
||||||
|
stream << static_cast<int>(right.data[right.size - 2 - i]) << ",";
|
||||||
|
}
|
||||||
|
stream << "]";
|
||||||
|
#else
|
||||||
|
// Печатаем самый большой разряд
|
||||||
|
stream << (int)right.data[right.size - 1];
|
||||||
|
|
||||||
|
// Печатаем остальные разряды с заполнением нулями до 2-х цифр
|
||||||
|
// setfill и setw это то же самое, что и в языке C спецификатор %02d
|
||||||
|
for (std::size_t i = 0; i < right.size - 1; ++i)
|
||||||
|
stream << std::setfill('0') << std::setw(2) << (int)right.data[right.size - 2 - i];
|
||||||
|
#endif
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
Number fib(int n) {
|
||||||
|
Number a = 0; // F0
|
||||||
|
Number b = 1; // F1
|
||||||
|
for (int i = 1; i <=n; ++i) {
|
||||||
|
if (i % 2) {
|
||||||
|
a += b;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
b += a;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (n % 2) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
return a;
|
||||||
|
}
|
||||||
|
|
||||||
|
Number factorial(int n) {
|
||||||
|
Number result{1};
|
||||||
|
for (int i = 2; i < n + 1; ++i) {
|
||||||
|
result = Number(i) * result;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
Number x = Number("25852016738884976640000");
|
||||||
|
Number y = Number("24");
|
||||||
|
|
||||||
|
//char s[3];
|
||||||
|
//Number result = "1";
|
||||||
|
//for (int i = 1; i < 26; ++i) {
|
||||||
|
//s = std::to_string(i);
|
||||||
|
//sprintf(s, "%d", i);
|
||||||
|
// result = (Number{i} * result);
|
||||||
|
//}
|
||||||
|
//x += y;
|
||||||
|
//Number z = x + y;
|
||||||
|
//std::cout << fib(1000) << std::endl;
|
||||||
|
//x = x * Number(24)*Number{25};
|
||||||
|
//y = factorial(5);
|
||||||
|
//std::cout << x << " " << x.capacity << " " << x.size << std::endl;
|
||||||
|
//std::cout << y << " "<< y.capacity << " " << y.size << std::endl;
|
||||||
|
// 90405070506200618121707-18-13-05-18-08
|
||||||
|
//std::cout << "===" << std::endl << Number(2) * Number(3) << " "<< Number(3) * Number(2) << std::endl;
|
||||||
|
//std::cout << "5! = " << Number(2) * Number(3) * Number(4) * Number(5) << std::endl;
|
||||||
|
std::cout << factorial(1000) << std::endl;
|
||||||
|
//std::cout << Number("620448401733239439360000") * Number(25) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
BIN
seminar02_encapsulation/homework/homework_encapsulation.pdf
Normal file
BIN
seminar02_encapsulation/homework/homework_encapsulation.pdf
Normal file
Binary file not shown.
202
seminar02_encapsulation/homework/homework_encapsulation.tex
Normal file
202
seminar02_encapsulation/homework/homework_encapsulation.tex
Normal file
|
|
@ -0,0 +1,202 @@
|
||||||
|
\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}
|
||||||
|
|
||||||
|
\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*{Класс Circle}
|
||||||
|
Допустим, что мы хотим создать программу, которая будет работать с окружностями (это может быть игра или, например, графический редактор). Для того, чтобы сделать код более понятным и удобным в использовании, мы решили создать класс окружности. Кроме того, мы решили использовать уже ранее написанный класс точки в 2D пространстве (файлы \texttt{point.h} и \texttt{point.cpp}). Создайте класс окружности, который будет включать следующие методы:
|
||||||
|
\begin{itemize}
|
||||||
|
\item Конструктор \texttt{Circle(const Point\& acenter, float aradius)}, который будет задавать поля \texttt{center} и \texttt{radius} соответстующими значениями.
|
||||||
|
\item Конструктор по умолчанию \texttt{Circle()} - задаются значения, соответствующие единичной окружности с центром в начале координат.
|
||||||
|
\item Конструктор копирования \texttt{Circle(const Circle\& circle)}
|
||||||
|
\item Сеттеры и геттеры, для полей \texttt{center} и \texttt{radius}. Поле \texttt{radius} нельзя задать отрицательным числом. При попытке задания его отрицательным числом оно должно устанавливаться в значение \texttt{0}.
|
||||||
|
\item Метод \texttt{float getArea() const}, который будет возвращать площадь поверхности круга.
|
||||||
|
\item Метод \texttt{float getDistance(const Point\& p) const}, который будет возвращать расстояние от точки \texttt{p}, до ближайшей точки окружности.
|
||||||
|
\item Метод \texttt{bool isColliding(const Circle\& c) const}, который будет возвращать \texttt{true}, если круг пересекается с кругом \texttt{c}.
|
||||||
|
\item Метод \texttt{void move(const Point\& p)}, который будет перемещать кружок на вектор \texttt{p}.
|
||||||
|
\end{itemize}
|
||||||
|
Весь начальный код содержится в папке \texttt{0circle}. При компиляции нужно указывать все \texttt{.cpp} файлы, которые вы хотите скомпилировать:
|
||||||
|
\begin{verbatim}
|
||||||
|
g++ main.cpp point.cpp
|
||||||
|
\end{verbatim}
|
||||||
|
\begin{itemize}
|
||||||
|
\item Создайте файлы \texttt{circle.h} и \texttt{circle.cpp} и перенесите реализацию класса окружности из файла \texttt{main.cpp} в эти файлы.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
|
||||||
|
\newpage
|
||||||
|
\section*{Класс Number (большое число)}
|
||||||
|
Стандартные целочисленные типы данных, такие как \texttt{int} имеют фиксированный небольшой размер. Соответственно значения, которые можно хранить в переменных этих типов ограничены. Типичное максимальное значение \texttt{char} равно $2^7 - 1 = 127$, тип \texttt{int} обычно ограничен $2^{31}-1 = 2147483647$ и даже тип \texttt{unsigned long long} имеет ограничение в $2^{64}-1 = 1.8 * 10^{19}$. Хранить действительно большие числа в этих типах невозможно. В этом задании нужно сделать класс, с помощью которого будет удобно складывать и умножать большие целые положительные числа. Начальный код этого класса содержится в \texttt{1number/number.cpp}. Изучите этот код.
|
||||||
|
|
||||||
|
|
||||||
|
\begin{figure}[h!]
|
||||||
|
\centering
|
||||||
|
\includegraphics[scale=1]{../images/number1.png}
|
||||||
|
\caption{Представление числа 12345678 в памяти с помощью нашего класса Number}
|
||||||
|
\label{fig:nummber1}
|
||||||
|
\end{figure}
|
||||||
|
|
||||||
|
|
||||||
|
\subsection*{Задания:}
|
||||||
|
\begin{itemize}
|
||||||
|
\item \textbf{Конструктор по умолчанию:} Напишите конструктор по умолчанию \texttt{Number()}, который будет создавать число равное нулю.
|
||||||
|
\item \textbf{Конструктор копирования:} Напишите конструктор копирования \texttt{Number(const Number\& n)}.
|
||||||
|
\item \textbf{Конструктор из строки:} Напишите конструктор \texttt{Number(const char* str)}, который будет создавать большое число на основе строки. Предполагаем, что на вход конструктору всегда идёт корректная строка. Например, число из примера можно будет создать так:
|
||||||
|
\begin{lstlisting}
|
||||||
|
Number a = Number("12345678");
|
||||||
|
\end{lstlisting}
|
||||||
|
\item \textbf{Присваивание:} Напишите оператор присваивания \texttt{Number\& operator=(const Number\& right)}.
|
||||||
|
\item \textbf{Сложение:} Напишите и протестируйте операторы сложения \texttt{operator+} и оператор присваивания сложения \texttt{operator+=}. Реализовывать оба этих оператора с нуля необязательно. Ведь, если написан один из этих операторов, то очень просто написать другой.
|
||||||
|
\item \textbf{Числа Фибоначчи:} Числа Фибоначчи задаются следующим образом:
|
||||||
|
\begin{align*}
|
||||||
|
F_0 &= 0\\
|
||||||
|
F_1 &= 1\\
|
||||||
|
F_n &= F_{n-1} + F_{n-2}
|
||||||
|
\end{align*}
|
||||||
|
Используйте класс \texttt{Number}, чтобы вычислить $F_{1000}$. Правильный ответ:
|
||||||
|
\begin{verbatim}
|
||||||
|
F(1000) = 43466557686937456435688527675040625802564660517371780402481729089536555417949051890
|
||||||
|
40387984007925516929592259308032263477520968962323987332247116164299644090653318793829896964992
|
||||||
|
8516003704476137795166849228875
|
||||||
|
\end{verbatim}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
\item \textbf{Четность:} Напишите метод \texttt{bool isEven() const}, который будет проверять является ли наше число чётным и, если это верно, возвращает \texttt{true}, в ином случае возвращает \texttt{false}.
|
||||||
|
|
||||||
|
\item \textbf{Произведение:} Напишите метод \texttt{Number operator*(const Number\& right) const} - оператор умножения одного числа \texttt{Number} на другое. Протестируйте вашу функцию на различных примерах (умножение большого числа на большое, умножение большого числа на небольшое ($< 100$) или на ноль, умножение двух небольших чисел и т. д.).\\
|
||||||
|
\item \textbf{Факториал:} Используйте написанный оператор для вычисления факториала от 1000. \\
|
||||||
|
Правильный ответ:
|
||||||
|
\begin{verbatim}
|
||||||
|
1000! = 40238726007709377354370243392300398571937486421071463254379991042993851239862902059
|
||||||
|
2044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759
|
||||||
|
9188236277271887325197795059509952761208749754624970436014182780946464962910563938874378864
|
||||||
|
8733711918104582578364784997701247663288983595573543251318532395846307555740911426241747434
|
||||||
|
9347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379
|
||||||
|
5345242215865932019280908782973084313928444032812315586110369768013573042161687476096758713
|
||||||
|
4831202547858932076716913244842623613141250878020800026168315102734182797770478463586817016
|
||||||
|
4365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186
|
||||||
|
1168115536158365469840467089756029009505376164758477284218896796462449451607653534081989013
|
||||||
|
8544248798495995331910172335555660213945039973628075013783761530712776192684903435262520001
|
||||||
|
5888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838
|
||||||
|
9714760885062768629671466746975629112340824392081601537808898939645182632436716167621791689
|
||||||
|
0977991190375403127462228998800519544441428201218736174599264295658174662830295557029902432
|
||||||
|
4153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690
|
||||||
|
8979684825901254583271682264580665267699586526822728070757813918581788896522081643483448259
|
||||||
|
9326604336766017699961283186078838615027946595513115655203609398818061213855860030143569452
|
||||||
|
7224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136
|
||||||
|
4932734975655139587205596542287497740114133469627154228458623773875382304838656889764619273
|
||||||
|
8381490014076731044664025989949022222176590433990188601856652648506179970235619389701786004
|
||||||
|
0811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614
|
||||||
|
8396573822911231250241866493531439701374285319266498753372189406942814341185201580141233448
|
||||||
|
2801505139969429015348307764456909907315243327828826986460278986432113908350621709500259738
|
||||||
|
9863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826
|
||||||
|
2809561214509948717012445164612603790293091208890869420285106401821543994571568059418727489
|
||||||
|
9809425474217358240106367740459574178516082923013535808184009699637252423056085590370062427
|
||||||
|
1243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||||
|
0000000000000000000000000000
|
||||||
|
\end{verbatim}
|
||||||
|
|
||||||
|
\item \textbf{Числа-градины:} Возьмём некоторое число $n$ и будем последовательно применять к нему следующую функцию:
|
||||||
|
\begin{equation*}
|
||||||
|
f(n) =
|
||||||
|
\begin{cases}
|
||||||
|
n / 2, &\textup{если n - четное}\\
|
||||||
|
3 n + 1, &\textup{если n - нечетное}
|
||||||
|
\end{cases}
|
||||||
|
\end{equation*}
|
||||||
|
В результате получится некоторая последовательность. Например, при $n = 7$ получится:
|
||||||
|
\begin{verbatim}
|
||||||
|
7 -> 22 -> 11 -> 34 -> 17 -> 52 -> 26 -> 13 -> 40 -> 20 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1
|
||||||
|
\end{verbatim}
|
||||||
|
Последовательность доходит до 1. Вам нужно написать функцию, которая будет по начальному числу находить длину такой последовательности (\texttt{steps}) и максимальное число в этой последовательности(\texttt{max}). Например, для числа $7$, максимальное число в последовательности будет равно $52$, а длина последовательности -- $16$. Напишите программу, которая будет по начальному числу находить длину последовательности и максимальный элемент в ней.
|
||||||
|
|
||||||
|
Тесты для проверки:
|
||||||
|
\begin{verbatim}
|
||||||
|
n = 7 steps = 16; max = 52
|
||||||
|
n = 256 steps = 8; max = 256
|
||||||
|
n = 1117065 steps = 527; max = 2974984576
|
||||||
|
n = 4761963248413673697 steps = 2337; max = 9926927712374950744648
|
||||||
|
|
||||||
|
n = 90560792656972947582439785608972465789628974587264056284658721771
|
||||||
|
steps = 1630;
|
||||||
|
max = 773658021643749360792171137214151494851244403993540980838080564520
|
||||||
|
\end{verbatim}
|
||||||
|
Для решения этой задачи нужно написать оператор сравнения и метод деления на 2 (оператор целочисленного деления можно не писать).
|
||||||
|
\item \textbf{Раздельная компиляция:} Перенесите объявление класса \texttt{Number} в файл \texttt{number.h}, а определение методов в файл \texttt{number.cpp}. Раздельно скомпилируйте эту программу.
|
||||||
|
\end{itemize}
|
||||||
|
|
||||||
|
\end{document}
|
||||||
BIN
seminar02_encapsulation/images/number1.png
Normal file
BIN
seminar02_encapsulation/images/number1.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
263
seminar02_encapsulation/images/number1.svg
Normal file
263
seminar02_encapsulation/images/number1.svg
Normal file
|
|
@ -0,0 +1,263 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="210mm"
|
||||||
|
height="297mm"
|
||||||
|
viewBox="0 0 210 297"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||||
|
sodipodi:docname="number1.svg"
|
||||||
|
inkscape:export-filename="C:\Users\vova\workspace\latex\cs_mipt_faki\term2\seminar02_encapsulation\images\number1.png"
|
||||||
|
inkscape:export-xdpi="300"
|
||||||
|
inkscape:export-ydpi="300">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="TriangleOutM"
|
||||||
|
orient="auto"
|
||||||
|
refY="0.0"
|
||||||
|
refX="0.0"
|
||||||
|
id="TriangleOutM"
|
||||||
|
style="overflow:visible"
|
||||||
|
inkscape:isstock="true">
|
||||||
|
<path
|
||||||
|
id="path1145"
|
||||||
|
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||||
|
transform="scale(0.4)" />
|
||||||
|
</marker>
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="1.4"
|
||||||
|
inkscape:cx="317.04261"
|
||||||
|
inkscape:cy="872.15364"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
inkscape:window-height="1377"
|
||||||
|
inkscape:window-x="-8"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#d7f4d7;fill-opacity:1;stroke:#000000;stroke-width:0.30000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="rect815"
|
||||||
|
width="23.450636"
|
||||||
|
height="8.9508085"
|
||||||
|
x="62.878162"
|
||||||
|
y="28.701445" />
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#d7f4d7;fill-opacity:1;stroke:#000000;stroke-width:0.30000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="rect815-2"
|
||||||
|
width="23.450638"
|
||||||
|
height="8.9508085"
|
||||||
|
x="62.878166"
|
||||||
|
y="37.652252" />
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#cccccc;fill-opacity:1;stroke:#000000;stroke-width:0.30000001;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="rect815-0"
|
||||||
|
width="23.450638"
|
||||||
|
height="8.9508085"
|
||||||
|
x="62.878166"
|
||||||
|
y="46.603043" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="73.134239"
|
||||||
|
y="35.031639"
|
||||||
|
id="text840"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan838"
|
||||||
|
x="73.134239"
|
||||||
|
y="35.031639"
|
||||||
|
style="stroke-width:0.26458332">4</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="50.580757"
|
||||||
|
y="111.18085"
|
||||||
|
id="text844"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan842"
|
||||||
|
x="50.580757"
|
||||||
|
y="115.4662"
|
||||||
|
style="stroke-width:0.26458332"></tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="73.19175"
|
||||||
|
y="43.75705"
|
||||||
|
id="text840-0"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan838-0"
|
||||||
|
x="73.19175"
|
||||||
|
y="43.75705"
|
||||||
|
style="stroke-width:0.26458332">5</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="51.218136"
|
||||||
|
y="34.563919"
|
||||||
|
id="text872"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan870"
|
||||||
|
x="51.218136"
|
||||||
|
y="34.563919"
|
||||||
|
style="stroke-width:0.26458332">size</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="40.424309"
|
||||||
|
y="43.743973"
|
||||||
|
id="text872-4"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan870-4"
|
||||||
|
x="40.424309"
|
||||||
|
y="43.743973"
|
||||||
|
style="stroke-width:0.26458332">capacity</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="51.084499"
|
||||||
|
y="53.3396"
|
||||||
|
id="text894"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan892"
|
||||||
|
x="51.084499"
|
||||||
|
y="53.3396"
|
||||||
|
style="stroke-width:0.26458332">data</tspan></text>
|
||||||
|
<circle
|
||||||
|
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.35941789;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="path896"
|
||||||
|
cx="74.336952"
|
||||||
|
cy="50.934158"
|
||||||
|
r="1.8411777" />
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#d7f4d7;fill-opacity:1;stroke:#000000;stroke-width:0.20522621;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="rect815-5"
|
||||||
|
width="11.451464"
|
||||||
|
height="8.5778608"
|
||||||
|
x="101.42937"
|
||||||
|
y="46.831276" />
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#d7f4d7;fill-opacity:1;stroke:#000000;stroke-width:0.20522621;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="rect815-5-8"
|
||||||
|
width="11.451464"
|
||||||
|
height="8.5778608"
|
||||||
|
x="112.88083"
|
||||||
|
y="46.831276" />
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#d7f4d7;fill-opacity:1;stroke:#000000;stroke-width:0.20522621;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="rect815-5-1"
|
||||||
|
width="11.451464"
|
||||||
|
height="8.5778608"
|
||||||
|
x="124.33229"
|
||||||
|
y="46.831276" />
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#d7f4d7;fill-opacity:1;stroke:#000000;stroke-width:0.20522621;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="rect815-5-5"
|
||||||
|
width="11.451464"
|
||||||
|
height="8.5778608"
|
||||||
|
x="135.78375"
|
||||||
|
y="46.831276" />
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#ebffeb;fill-opacity:1;stroke:#000000;stroke-width:0.20522621;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="rect815-5-82"
|
||||||
|
width="11.451464"
|
||||||
|
height="8.5778608"
|
||||||
|
x="147.23523"
|
||||||
|
y="46.831276" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="104.47309"
|
||||||
|
y="52.654404"
|
||||||
|
id="text840-07"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan838-4"
|
||||||
|
x="104.47309"
|
||||||
|
y="52.654404"
|
||||||
|
style="stroke-width:0.26458332">78</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="115.86423"
|
||||||
|
y="52.529114"
|
||||||
|
id="text840-07-9"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan838-4-7"
|
||||||
|
x="115.86423"
|
||||||
|
y="52.529114"
|
||||||
|
style="stroke-width:0.26458332">56</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="127.49047"
|
||||||
|
y="52.54583"
|
||||||
|
id="text840-07-4"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan838-4-8"
|
||||||
|
x="127.49047"
|
||||||
|
y="52.54583"
|
||||||
|
style="stroke-width:0.26458332">43</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="139.01648"
|
||||||
|
y="52.495712"
|
||||||
|
id="text840-07-8"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan838-4-9"
|
||||||
|
x="139.01648"
|
||||||
|
y="52.495712"
|
||||||
|
style="stroke-width:0.26458332">12</tspan></text>
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:0.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#TriangleOutM)"
|
||||||
|
d="m 74.537403,51.067801 c 4.677216,-0.36749 21.181108,-0.8018 24.288118,-0.80179"
|
||||||
|
id="path998"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cc" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="63.742908"
|
||||||
|
y="27.441465"
|
||||||
|
id="text1806"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan1804"
|
||||||
|
x="63.742908"
|
||||||
|
y="27.441465"
|
||||||
|
style="stroke-width:0.26458332">Number</tspan></text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 13 KiB |
BIN
seminar02_encapsulation/images/sepcompilation.png
Normal file
BIN
seminar02_encapsulation/images/sepcompilation.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 304 KiB |
338
seminar02_encapsulation/images/sepcompilation.svg
Normal file
338
seminar02_encapsulation/images/sepcompilation.svg
Normal file
|
|
@ -0,0 +1,338 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="210mm"
|
||||||
|
height="297mm"
|
||||||
|
viewBox="0 0 210 297"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||||
|
sodipodi:docname="sepcompilation.svg"
|
||||||
|
inkscape:export-filename="C:\Users\vova\workspace\latex\cs_mipt_faki\term2\seminar02_encapsulation\images\sepcompilation.png"
|
||||||
|
inkscape:export-xdpi="300"
|
||||||
|
inkscape:export-ydpi="300">
|
||||||
|
<defs
|
||||||
|
id="defs2" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.98994949"
|
||||||
|
inkscape:cx="243.20281"
|
||||||
|
inkscape:cy="570.05869"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
inkscape:window-height="1377"
|
||||||
|
inkscape:window-x="-8"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#e7eef4;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="rect815"
|
||||||
|
width="138.83838"
|
||||||
|
height="58.966839"
|
||||||
|
x="23.432297"
|
||||||
|
y="13.06549" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="28.503822"
|
||||||
|
y="24.373625"
|
||||||
|
id="text823"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan821"
|
||||||
|
x="28.503822"
|
||||||
|
y="24.373625"
|
||||||
|
style="stroke-width:0.26458332"><tspan
|
||||||
|
style="fill:#0000ff"
|
||||||
|
id="tspan845">struct</tspan> Point {</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="28.503822"
|
||||||
|
y="30.547235"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan825"> <tspan
|
||||||
|
style="fill:#0000ff"
|
||||||
|
id="tspan837">float</tspan> x, y;</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="28.503822"
|
||||||
|
y="36.720848"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan827"></tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="28.503822"
|
||||||
|
y="42.894459"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan829"> <tspan
|
||||||
|
style="fill:#0000ff"
|
||||||
|
id="tspan841">float</tspan> norm() const;</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="28.503822"
|
||||||
|
y="49.068069"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan831"> <tspan
|
||||||
|
style="fill:#0000ff"
|
||||||
|
id="tspan843">void</tspan> normalize();</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="28.503822"
|
||||||
|
y="55.24168"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan833"> Point <tspan
|
||||||
|
style="fill:#0000ff"
|
||||||
|
id="tspan847">operator</tspan>+(<tspan
|
||||||
|
style="fill:#0000ff"
|
||||||
|
id="tspan851">const</tspan> Point& r) <tspan
|
||||||
|
style="fill:#0000ff"
|
||||||
|
id="tspan849">const</tspan>;</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="28.503822"
|
||||||
|
y="61.415291"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan835">};</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="25.79151"
|
||||||
|
y="11.021605"
|
||||||
|
id="text855"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan853"
|
||||||
|
x="25.79151"
|
||||||
|
y="11.021605"
|
||||||
|
style="stroke-width:0.26458332">point.h</tspan></text>
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#e7eef4;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="rect815-8"
|
||||||
|
width="139.52013"
|
||||||
|
height="114.80299"
|
||||||
|
x="23.665709"
|
||||||
|
y="86.590546" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="26.57818"
|
||||||
|
y="89.27375"
|
||||||
|
id="text823-4"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="26.57818"
|
||||||
|
y="89.27375"
|
||||||
|
style="fill:#0000ff;stroke-width:0.26458332"
|
||||||
|
id="tspan835-0"> </tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="26.57818"
|
||||||
|
y="95.447365"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan1159"><tspan
|
||||||
|
style="fill:#0000ff"
|
||||||
|
id="tspan1161">#include</tspan> <cmath></tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="26.57818"
|
||||||
|
y="101.62097"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan1163"><tspan
|
||||||
|
style="fill:#0000ff"
|
||||||
|
id="tspan1171">#include</tspan> "point.h"</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="26.57818"
|
||||||
|
y="107.79458"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan997" /><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="26.57818"
|
||||||
|
y="113.96819"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan995"><tspan
|
||||||
|
style="fill:#0000ff"
|
||||||
|
id="tspan1001">float</tspan> Point::norm() <tspan
|
||||||
|
style="fill:#0000ff"
|
||||||
|
id="tspan1003">const</tspan> {</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="26.57818"
|
||||||
|
y="120.14181"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan969"> <tspan
|
||||||
|
style="fill:#0000ff"
|
||||||
|
id="tspan1005">return</tspan> sqrt(x*x + y*y);</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="26.57818"
|
||||||
|
y="126.31542"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan971">}</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="26.57818"
|
||||||
|
y="132.48901"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan973" /><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="26.57818"
|
||||||
|
y="138.66263"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan975"><tspan
|
||||||
|
style="fill:#0000ff"
|
||||||
|
id="tspan1007">void</tspan> Point::normalize() {</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="26.57818"
|
||||||
|
y="144.83624"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan977"> <tspan
|
||||||
|
style="fill:#0000ff"
|
||||||
|
id="tspan1009">float</tspan> pnorm = norm();</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="26.57818"
|
||||||
|
y="151.00984"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan979"> x /= pnorm;</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="26.57818"
|
||||||
|
y="157.18346"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan981"> y /= pnorm;</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="26.57818"
|
||||||
|
y="163.35707"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan983">}</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="26.57818"
|
||||||
|
y="169.53069"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan985" /><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="26.57818"
|
||||||
|
y="175.7043"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan987">Point Point::<tspan
|
||||||
|
style="fill:#0000ff"
|
||||||
|
id="tspan1011">operator</tspan>+(<tspan
|
||||||
|
style="fill:#0000ff"
|
||||||
|
id="tspan1013">const</tspan> Point& r) <tspan
|
||||||
|
style="fill:#0000ff"
|
||||||
|
id="tspan1015">const</tspan>{</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="26.57818"
|
||||||
|
y="181.8779"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan989"> Point result = {x + r.x, y + r.y};</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="26.57818"
|
||||||
|
y="188.05151"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan991"> <tspan
|
||||||
|
style="fill:#0000ff"
|
||||||
|
id="tspan1017">return</tspan> result;</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="26.57818"
|
||||||
|
y="194.22513"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan993">}</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="25.736752"
|
||||||
|
y="81.801659"
|
||||||
|
id="text855-9"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan853-3"
|
||||||
|
x="25.736752"
|
||||||
|
y="81.801659"
|
||||||
|
style="stroke-width:0.26458332">point.cpp</tspan></text>
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#e7eef4;fill-opacity:1;stroke:#000000;stroke-width:0.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="rect815-6"
|
||||||
|
width="139.8732"
|
||||||
|
height="58.965"
|
||||||
|
x="23.31591"
|
||||||
|
y="215.80164" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="28.386515"
|
||||||
|
y="227.10884"
|
||||||
|
id="text823-9"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="28.386515"
|
||||||
|
y="227.10884"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan835-8"><tspan
|
||||||
|
style="fill:#0000ff"
|
||||||
|
id="tspan1149">#include</tspan> <iostream></tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="28.386515"
|
||||||
|
y="233.28246"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan1143"><tspan
|
||||||
|
style="fill:#0000ff"
|
||||||
|
id="tspan1151">#include</tspan> "point.h"</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="28.386515"
|
||||||
|
y="239.45607"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan1145" /><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="28.386515"
|
||||||
|
y="245.62967"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan1141"><tspan
|
||||||
|
style="fill:#0000ff"
|
||||||
|
id="tspan1153">int</tspan> main() {</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="28.386515"
|
||||||
|
y="251.80327"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan1131"> Point p = {1, 2};</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="28.386515"
|
||||||
|
y="257.97687"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan1133"> p.normalize();</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="28.386515"
|
||||||
|
y="264.15048"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan1137"> std::cout << p.x << " " << p.y << std::endl;</tspan><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
x="28.386515"
|
||||||
|
y="270.3241"
|
||||||
|
style="stroke-width:0.26458332"
|
||||||
|
id="tspan1139">}</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="25.674202"
|
||||||
|
y="213.75682"
|
||||||
|
id="text855-5"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan853-9"
|
||||||
|
x="25.674202"
|
||||||
|
y="213.75682"
|
||||||
|
style="stroke-width:0.26458332">main.cpp</tspan></text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 13 KiB |
BIN
seminar02_encapsulation/images/string_base.png
Normal file
BIN
seminar02_encapsulation/images/string_base.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
344
seminar02_encapsulation/images/string_base.svg
Normal file
344
seminar02_encapsulation/images/string_base.svg
Normal file
|
|
@ -0,0 +1,344 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="210mm"
|
||||||
|
height="297mm"
|
||||||
|
viewBox="0 0 210 297"
|
||||||
|
version="1.1"
|
||||||
|
id="svg8"
|
||||||
|
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
||||||
|
sodipodi:docname="string_base.svg"
|
||||||
|
inkscape:export-filename="C:\Users\vova\workspace\latex\cs_mipt_faki\term2\seminar02_encapsulation\images\string_base.png"
|
||||||
|
inkscape:export-xdpi="300"
|
||||||
|
inkscape:export-ydpi="300">
|
||||||
|
<defs
|
||||||
|
id="defs2">
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="TriangleOutM"
|
||||||
|
orient="auto"
|
||||||
|
refY="0.0"
|
||||||
|
refX="0.0"
|
||||||
|
id="marker5033"
|
||||||
|
style="overflow:visible"
|
||||||
|
inkscape:isstock="true">
|
||||||
|
<path
|
||||||
|
id="path5031"
|
||||||
|
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||||
|
transform="scale(0.4)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="TriangleOutL"
|
||||||
|
orient="auto"
|
||||||
|
refY="0.0"
|
||||||
|
refX="0.0"
|
||||||
|
id="TriangleOutL"
|
||||||
|
style="overflow:visible"
|
||||||
|
inkscape:isstock="true">
|
||||||
|
<path
|
||||||
|
id="path4853"
|
||||||
|
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||||
|
transform="scale(0.8)" />
|
||||||
|
</marker>
|
||||||
|
<marker
|
||||||
|
inkscape:stockid="TriangleOutM"
|
||||||
|
orient="auto"
|
||||||
|
refY="0.0"
|
||||||
|
refX="0.0"
|
||||||
|
id="TriangleOutM"
|
||||||
|
style="overflow:visible"
|
||||||
|
inkscape:isstock="true">
|
||||||
|
<path
|
||||||
|
id="path4856"
|
||||||
|
d="M 5.77,0.0 L -2.88,5.0 L -2.88,-5.0 L 5.77,0.0 z "
|
||||||
|
style="fill-rule:evenodd;stroke:#000000;stroke-width:1pt;stroke-opacity:1;fill:#000000;fill-opacity:1"
|
||||||
|
transform="scale(0.4)" />
|
||||||
|
</marker>
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="0.98994949"
|
||||||
|
inkscape:cx="315.82303"
|
||||||
|
inkscape:cy="843.84077"
|
||||||
|
inkscape:document-units="mm"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="false"
|
||||||
|
showguides="false"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
inkscape:window-height="1377"
|
||||||
|
inkscape:window-x="-8"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1" />
|
||||||
|
<metadata
|
||||||
|
id="metadata5">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer"
|
||||||
|
id="layer1">
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#d7f4d7;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="rect4520"
|
||||||
|
width="30.468725"
|
||||||
|
height="9.6217022"
|
||||||
|
x="39.030174"
|
||||||
|
y="38.982063" />
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#e6e6e6;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="rect4520-4"
|
||||||
|
width="30.468725"
|
||||||
|
height="9.6217022"
|
||||||
|
x="39.030174"
|
||||||
|
y="48.603767" />
|
||||||
|
<circle
|
||||||
|
style="opacity:1;fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:0.44303662;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="path4543"
|
||||||
|
cx="54.455605"
|
||||||
|
cy="53.397713"
|
||||||
|
r="2.573324" />
|
||||||
|
<flowRoot
|
||||||
|
xml:space="preserve"
|
||||||
|
id="flowRoot4545"
|
||||||
|
style="fill:black;fill-opacity:1;stroke:none;font-family:Consolas;font-style:normal;font-weight:normal;font-size:18.66666667px;line-height:1.25;letter-spacing:0px;word-spacing:0px;-inkscape-font-specification:'Consolas, Normal';font-stretch:normal;font-variant:normal;text-anchor:start;text-align:start;writing-mode:lr;font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal"><flowRegion
|
||||||
|
id="flowRegion4547"><rect
|
||||||
|
id="rect4549"
|
||||||
|
width="38.385796"
|
||||||
|
height="35.860416"
|
||||||
|
x="342.94678"
|
||||||
|
y="370.46112" /></flowRegion><flowPara
|
||||||
|
id="flowPara4551"></flowPara></flowRoot> <rect
|
||||||
|
style="opacity:1;fill:#fff6d5;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="rect4553"
|
||||||
|
width="11.626225"
|
||||||
|
height="9.0871639"
|
||||||
|
x="91.456924"
|
||||||
|
y="44.917343" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="95.248917"
|
||||||
|
y="51.714432"
|
||||||
|
id="text4566"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan4564"
|
||||||
|
x="95.248917"
|
||||||
|
y="51.714432"
|
||||||
|
style="font-size:7.05555534px;stroke-width:0.26458332">E</tspan></text>
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#fff6d5;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="rect4553-2"
|
||||||
|
width="11.626225"
|
||||||
|
height="9.0871639"
|
||||||
|
x="103.08315"
|
||||||
|
y="44.917343" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="106.99326"
|
||||||
|
y="51.714439"
|
||||||
|
id="text4566-3"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan4564-3"
|
||||||
|
x="106.99326"
|
||||||
|
y="51.714439"
|
||||||
|
style="font-size:7.05555534px;stroke-width:0.26458332">l</tspan></text>
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#fff6d5;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="rect4553-2-8"
|
||||||
|
width="11.626225"
|
||||||
|
height="9.0871639"
|
||||||
|
x="114.70938"
|
||||||
|
y="44.917343" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="118.61949"
|
||||||
|
y="51.714439"
|
||||||
|
id="text4566-3-5"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan4564-3-6"
|
||||||
|
x="118.61949"
|
||||||
|
y="51.714439"
|
||||||
|
style="font-size:7.05555534px;stroke-width:0.26458332">e</tspan></text>
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#fff6d5;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="rect4553-2-4"
|
||||||
|
width="11.626225"
|
||||||
|
height="9.0871639"
|
||||||
|
x="126.33562"
|
||||||
|
y="44.917343" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="130.24574"
|
||||||
|
y="51.714439"
|
||||||
|
id="text4566-3-6"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan4564-3-7"
|
||||||
|
x="130.24574"
|
||||||
|
y="51.714439"
|
||||||
|
style="font-size:7.05555534px;stroke-width:0.26458332">p</tspan></text>
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#fff6d5;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="rect4553-2-8-4"
|
||||||
|
width="11.626225"
|
||||||
|
height="9.0871639"
|
||||||
|
x="137.96185"
|
||||||
|
y="44.917343" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="141.87195"
|
||||||
|
y="51.714439"
|
||||||
|
id="text4566-3-5-0"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan4564-3-6-4"
|
||||||
|
x="141.87195"
|
||||||
|
y="51.714439"
|
||||||
|
style="font-size:7.05555534px;stroke-width:0.26458332">h</tspan></text>
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#fff6d5;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="rect4553-2-6"
|
||||||
|
width="11.626225"
|
||||||
|
height="9.0871639"
|
||||||
|
x="149.58807"
|
||||||
|
y="44.917343" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="153.49818"
|
||||||
|
y="51.714447"
|
||||||
|
id="text4566-3-8"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan4564-3-0"
|
||||||
|
x="153.49818"
|
||||||
|
y="51.714447"
|
||||||
|
style="font-size:7.05555534px;stroke-width:0.26458332">a</tspan></text>
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#fff6d5;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="rect4553-2-8-5"
|
||||||
|
width="11.626225"
|
||||||
|
height="9.0871639"
|
||||||
|
x="161.21431"
|
||||||
|
y="44.917343" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="165.12442"
|
||||||
|
y="51.714447"
|
||||||
|
id="text4566-3-5-9"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan4564-3-6-2"
|
||||||
|
x="165.12442"
|
||||||
|
y="51.714447"
|
||||||
|
style="font-size:7.05555534px;stroke-width:0.26458332">n</tspan></text>
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#fff6d5;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="rect4553-2-61"
|
||||||
|
width="11.626225"
|
||||||
|
height="9.0871639"
|
||||||
|
x="172.84053"
|
||||||
|
y="44.917343" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="176.75064"
|
||||||
|
y="51.714432"
|
||||||
|
id="text4566-3-7"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan4564-3-9"
|
||||||
|
x="176.75064"
|
||||||
|
y="51.714432"
|
||||||
|
style="font-size:7.05555534px;stroke-width:0.26458332">t</tspan></text>
|
||||||
|
<rect
|
||||||
|
style="opacity:1;fill:#fff6d5;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
id="rect4553-2-8-57"
|
||||||
|
width="11.626225"
|
||||||
|
height="9.0871639"
|
||||||
|
x="184.46677"
|
||||||
|
y="44.917343" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="186.10507"
|
||||||
|
y="51.714432"
|
||||||
|
id="text4566-3-5-96"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan4564-3-6-9"
|
||||||
|
x="186.10507"
|
||||||
|
y="51.714432"
|
||||||
|
style="font-size:7.05555534px;stroke-width:0.26458332">\0</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="52.359035"
|
||||||
|
y="45.97747"
|
||||||
|
id="text4566-0"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan4564-37"
|
||||||
|
x="52.359035"
|
||||||
|
y="45.97747"
|
||||||
|
style="font-size:7.05555534px;stroke-width:0.26458332">8</tspan></text>
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;marker-end:url(#marker5033)"
|
||||||
|
d="M 54.1309,53.481438 C 68.229368,51.744187 78.051525,49.806481 86.938236,49.539213"
|
||||||
|
id="path4709"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="39.555893"
|
||||||
|
y="36.946739"
|
||||||
|
id="text5223"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan5221"
|
||||||
|
x="39.555893"
|
||||||
|
y="36.946739"
|
||||||
|
style="font-size:4.23333311px;stroke-width:0.26458332">String a</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="28.549953"
|
||||||
|
y="45.468987"
|
||||||
|
id="text5223-0"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan5221-1"
|
||||||
|
x="28.549953"
|
||||||
|
y="45.468987"
|
||||||
|
style="font-size:4.23333311px;stroke-width:0.26458332">size</tspan></text>
|
||||||
|
<text
|
||||||
|
xml:space="preserve"
|
||||||
|
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:4.93888855px;line-height:1.25;font-family:Consolas;-inkscape-font-specification:'Consolas, Normal';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-feature-settings:normal;text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332"
|
||||||
|
x="28.480877"
|
||||||
|
y="55.038445"
|
||||||
|
id="text5223-0-0"><tspan
|
||||||
|
sodipodi:role="line"
|
||||||
|
id="tspan5221-1-1"
|
||||||
|
x="28.480877"
|
||||||
|
y="55.038445"
|
||||||
|
style="font-size:4.23333311px;stroke-width:0.26458332">data</tspan></text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 17 KiB |
Reference in a new issue