С++, начала ООП Семинар 1 Рябова Анна Сергеевна
Некоторые отличия C++ от C /* комментарий в стиле C */ // Пример комментария в С++ Значения аргументов по умолчанию int factorial( int n=0) Неименованные параметры int f(int x, int, int z) { return x+z; } Создание переменных в любом месте программы for(int i = 0; i < 5; i++) inline функции макрос #define sqr(x) ((x)*(x)) : в тексте программы замена sqr(i) на ((i)*(i)). если sqr(i++), чему равно i? inline int sqr(int i) { return i*i; }
Некоторые отличия C++ от C Доступ к замаскированной глобальной переменной int i; // global scope variable void f() { int i; i = 0; // Local i used ::i=0 // Global i used, would be impossible in C } Операторы new/deleteдля работы с памятью int *p = malloc(sizeof(int)); free(p); int *p = new int; delete p; int *q = malloc(5 * sizeof(int)); free(q); int *q = new int[5]; delete[] q;
Некоторые отличия C++ от C пространства имен namespace kids { int getWorkDays {... }; }; namespace adults { int getWorkDays {... }; }; if(adults::getWorkDays() y ? x : y ; } int a; a = max(1, 3); double d; d = max(2.5, -1.0);
Некоторые отличия C++ от C Потоки ввода-вывода #include using namespace std; int main() { string name; int age; cout name >> age ; cout
Некоторые отличия C++ от C ссылки int i; int& ref = i; //обязательно явно инициализировать ссылку! ref = 3 //i станет равно 3 // C-style (pointers) void swap(int *a, int *b) { int temp = *a; *a = *b; *b = temp; } int i = 1, j = 2; swap(&i,&j); // Now i==2 and j==1 int& ret_arg(int &arg) { return arg; } int i; ret_arg(i) = 2; // Now i==2 // C++-style (references) void swap(int& a, int& b) { int temp = a; a = b; b = temp; } int i = 1, j = 2; swap(i,j); // Now i==2 and j==1
Структура struct Complex { int Re; //Действительная часть int Im; //Мнимая часть } struct Complex a; a.Re = 1; a.Im = 0; struct Complex *p = &a; p->Im = 0; Структура не знала, как будут использоваться ее данные struct Complex add(struct Complex a, struct Complex b) { struct Complex result; result.Re = a.Re + b.Re; result.Im = a.Im + b.Im; return result; }
Структура: недостатки с = add(a,b) вместо c = a + b если функция должна изменить аргумент, надо передавать адрес структуры нет защиты от некорректных действий создание комплексного числа – объявление переменной, инициализация полей если структура имеет дело с памятью (содержит указатели), то надо следить за памятью при возврате из функций
Структура в C++ Имя структуры – имя типа: Complex a; вместо struct Complex a; Структура может содержать методы struct Complex { int Re; //Действительная часть int Im; //Мнимая часть double module(); } double Complex::module() { return sqrt(Re*Re + Im*Im); } Complex a; a.Re = 1; a.Im = 3; double mod = a.module();
Структуры: доступ private – личные данные, доступны только методам структуры public – доступны всем (по умолчанию все поля публичные) struct Complex { private: int Re; //Действительная часть int Im; //Мнимая часть public: int getRe() const { return Re; } int getIm() const { return Im; } int setValue(int re, int im) { if(re == im) { // Сообщить об ошибке return; } Re = re; Im = im; }
Классы Превратить структуру в класс очень просто – надо заменить ключевое слово struct на class. Отличие - права доступа по умолчанию. В классе все поля и функции, для которых явно не указан уровень доступа, считаются личными (private) struct Complex { private: int Re; int Im; Объект (экземпляр) – это отдельный представитель класса, имеющий конкретное состояние и поведение, полностью определяемое классом. Интерфейс – это набор методов класса, доступных для использования другими классами. class Complex { int Re; int Im;
Классы: конструктор Конструктор – метод, который вызывается при создании нового экземпляра класса Имя совпадает с именем класса Тип возвращаемого значения отсутсвтует Один класс может содержать несколько конструкторов с разным набором параметров, нужный выбирается автоматически class Complex { int Re, Im; public: Complex(int re, int im = 0) { Re = re; Im = im; } Complex() { Re = 0; Im = 0; } }; Complex a(1,1), b(3), c; //Использование В конструкторе может содержаться выделение памяти, открытие файлов и т.п.
Классы: конструктор копирования Копирующий конструктор позволяет инициализировать новый объект другим объектом того же типа A::A(const A&); Если не задан явно, создается автоматически Автоматический конструктор - почленное копирование Если поле – объект другого класса, почленное копирование вызывает копирующий конструктор для этого поля Для встроенных типов и для классов почленное копирование – побитовое копирование содержимого из одного объекта в другой class Complex { int Re, Im; public: Complex(Complex c) { Re = c.Re; Im = c.Im; } }; Complex b(2,3); //Обычный конструктор Complex a(b); //Конструктор копирования
Классы: деструктор Деструктор – метод, котрый вызывается при удалении объекта Имя совпадает с именем класса, с префиксом ~ (тильда (в левом верхнем углу клавиатуры) ) Не имеет параметров class Complex { … public: ~Complex() { } В деструкторе можно освобождать память, закрывать файлы
Классы: друзья Если все же нужен доступ к private полям? (Например, функции требуется полный доступ к полям двух классов) Друзья класса - функции и классы, у которых есть полный доступ к private полям класса (такой же доступ, как у его собственных функций). Ключевое слово friend Функция print_fields(A a) имеет полный доступ к private полям класса A. friend-объявление распространяется только на функцию с указанной сигнатурой, в нашем случае print_fields(A), а не на все функции с именем print_fields. friend class B; делает поля класса A доступными для всех функций- членов класса B. class B; class A { int n1, n2; friend void print_fields(A a); friend class B; public: set_fields(n_1,n_2 ) { n1 = n_1; n2 = n_2; } }; void print_fields(A a) { cout
Операторы: сложение Можно определить для класса стандартные операторы (+, * и т.д.) class Complex { … Complex operator+(const Complex& b) { Complex result(Re + b.Re, Im + b.Im); return result; } }; Параметр передается по ссылке, чтобы избежать лишнего копирования Использование: Complex a(1,1), b(2,2), c; c = a+b; //Вызовется a.operator+(b);
Операторы: присваивание Оператор присваивания тоже можно переопределить class Complex { … Complex& operator=(const Complex& b) { if(&b != this) { Re = b.Re; Im = b.Im; } return *this; } Возвращает ссылку, чтобы можно было писать цепочку присваивания a=b=c Похож на конструктор копирования, но объект уже создан Complex a = b; //Конструктор копирования a = b; //Присваивание
Операторы: приведение типа class Complex { … operator double() const { return sqrt(Re*Re + Im*Im); } }; Complex a(2,2); double b = sqrt(a);
Дополнительно Оператор new вызывает конструктор, delete - деструктор
Литература Х. Дейтел, П. Дейтел Как программировать на C++ Бьярн Страуструп Справочное руководство по C++ Лаптев В.В. и др. С++. Объектно-ориентированное программирование
Упражнение 1 Реализовать класс SomeClass. Продумать структуру (количество и тип полей). Обязательно должны быть: А) Конструктор, в котором кроме инициализации полей объекта должна выводиться строка вида «Создан объект класса SomeClass» Б) Деструктор, в котором кроме освобождения памяти (если необходимо по заданию) должна выводиться строка вида «Уничтожен объект класса SomeClass» В) Метод вывода на экран Display Реализовать какой-либо метод, по смыслу относящийся к данному классу. Возможные классы: Point – точка в декартовой СК Rational – рациональная дробь Money – деньги Data – календарная дата Time – Время Auto – Автомобиль (марка, год выпуска) User – Пользователь (форума, компьютера) Vector3D – вектор в трехмерном пространстве Triangle – треугольник Company – фирма …
Задание 1 Реализовать класс Vector для работы с целочисленными векторами в n-мерном пространстве. Вектор задается как динамический массив целых чисел (int*) и помнит свою длину. class Vector { private: int n; int* data; }; Аккуратно работайте с памятью: выделение – в конструкторе, освобождение в деструкторе. Необходимо реализовать: на тройку: Конструктор по умолчанию Конструктор с заданной длиной вектора Vector(int) Конструктор Vector(int size, int value), заполняющий весь вектор значениями value Деструктор Операцию вычисления длины вектора (корень из суммы квадратов) Скалярное произведение на четверку Конструктор копирования Оператор operator+ Оператор присваивания на пятерку Обращение по индексу
Требования Всего будет 4 задачи За задачу можно получить 5,4,3 или 0 баллов Итоговая оценка – среднеарифметическое За одно занятие сдавать не более двух заданий Начинать сдавать задания не позже 1 декабря Можно сдавать задачу по частям (сначала на 3, потом повысить оценку)