seminar2
This commit is contained in:
parent
46d1c64684
commit
ab6732eded
98 changed files with 10319 additions and 0 deletions
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();
|
||||
}
|
||||
Reference in a new issue