Классы и объекты в С++

Содержание

Слайд 2

Вопросы для повторения

Из каких шагов состоит построение программы на C++?
Как в тексте

Вопросы для повторения Из каких шагов состоит построение программы на C++? Как
программы обнаружить инструкции препроцессора? Приведите примеры инструкций препроцессора.
Назовите 4 основных типа данных, определенных в языке C++.
Можно ли в C++ написать x = y = 3? Почему?
Можно ли вызвать void foo(int & a) следующим образом: foo(x+y); Почему?
Проинтерпретируйте объявление второго параметра main. int main(int argc, char* argv[])
Сколько операций умножения в операторе *p = *p * 2?
Если массив w проинициализирован значениями 1, 2, 3. Чему равно значение выражения *w?
Чему равна величина p + i, где p – указатель на массив целых, а i – целое число?

Слайд 3

Содержание

Классы, структуры, объекты
Время жизни переменных (объектов)
Конструкторы инициализации
Структуры
Наследование
Шаблоны
Inline функции и методы
Переопределение операций
Управление памятью

Содержание Классы, структуры, объекты Время жизни переменных (объектов) Конструкторы инициализации Структуры Наследование
и динамические объекты
Глобальные переменные и статические поля
Виды конструкторов в C++
Конструктор по умолчанию
Конструктор инициализации
Конструктор копирования
Ссылки в C# (.Net)
Строки STL и консольный ввод

Слайд 4

Классы, структуры, объекты*

Классы объявляются по аналогии с C#
class Date {
int m_nYear;
int m_nMonth;
int

Классы, структуры, объекты* Классы объявляются по аналогии с C# class Date {
m_nDay;
public: //Указывается не перед каждым методом
Date(); //Конструктор, как правило, public
~Date() {}
}; //Точка с запятой обязательна!
Объявления, как правило, в заголовочном файле (интерфейс). Реализация часто в CPP-файле

Слайд 5

Реализация методов*

Date.cpp
#include “Date.h”
Date::Date () { //Указываем класс
m_nYear = 1;
m_nMonth = 1;
m_nDay

Реализация методов* Date.cpp #include “Date.h” Date::Date () { //Указываем класс m_nYear =
= 1;
}
Такой конструктор по умолчанию создает объект-даты 1 янв. 0001 года.

Слайд 6

Объявление и время жизни объектов*

#include “Date.h”
 int main(){
Date d; // Это не ссылка,

Объявление и время жизни объектов* #include “Date.h” int main(){ Date d; //
а объект!
return 0;
}
Локальные объекты создаются при выполнении объявления.
Локальные объекты исчезают по завершении блока в котором они были объявлены.
Глобальные объекты объявляются вне блоков.
Глобальные объекты создаются до начала работы программы, а разрушаются после завершения программы.

Слайд 7

Конструкторы инициализации*

class Date {
int m_nYear;
int m_nMonth;
int m_nDay;
public:
Date();
Date(int year, int mon=1, int day=1);
~Date()

Конструкторы инициализации* class Date { int m_nYear; int m_nMonth; int m_nDay; public:
{}
};
Параметры по умолчанию задаются при объявлении!

Слайд 8

Конструкторы инициализации

Date::Date (int year, int mon, int day) {
if (year <

Конструкторы инициализации Date::Date (int year, int mon, int day) { if (year
1 || year > 10000)
year = 1;
if (mon < 1 || mon > 12)
mon = 1;
int vDays[12]={31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
if (mon < 1 || mon > 12)
mon = 1;
if (day < 1 || day > vDays[mon-1])
day = 1;
if (mon == 2)
if(day == 29 && (year % 4 > 0 || (year % 100 == 0 && year % 400 >0))) {
day = 1;
mon = 3;
}
m_nYear = year;
m_nMonth = mon;
m_nDay = day;
}
Конструктор обеспечивает правильность создаваемой даты
Date d(2006, 10, 12), t(2006, 11), e(2006);

Слайд 9

Структуры*

Структуры – те же классы!
По умолчанию в них действует область видимости public
struct

Структуры* Структуры – те же классы! По умолчанию в них действует область
Date {
private:
int m_nYear;
int m_nMonth;
int m_nDay;
public:
Date();
~Date() {} //Конструктор, как правило, public
}; //Точка с запятой обязательна!

Слайд 10

Структуры в C#

В C# между структурами и классами имеются существенные различия!
Все структуры

Структуры в C# В C# между структурами и классами имеются существенные различия!
в C# являются Value Type! В том числе, числовые типы, перечисления и пр.
Все классы – Reference Type

Слайд 11

Наследование

class B //Доступом к предку можно управлять
{
public:
void boo();
};
class C: B class C:

Наследование class B //Доступом к предку можно управлять { public: void boo();
public B
{ {
… …
}; };
C c; C c;
c.boo(); c.boo();

Слайд 12

Включение и наследование

class B
{
public:
void boo();
};
class C
{
public:
B m_B;
};
C c;
c.m_B.boo();

Включение и наследование class B { public: void boo(); }; class C

Слайд 13

Предки как неименованные члены класса*

class C{ public: B m_B} class C: public B

Предки как неименованные члены класса* class C{ public: B m_B} class C:
{}
с.m_B.boo() c.boo()
Есть и существенные различия (см. комментарий к слайду).

C c

B m_B

C c

B

Слайд 14

Шаблоны

Шаблоны – абстракции типов и алгоритмов
Шаблон алгоритма:
template void Swap (T&

Шаблоны Шаблоны – абстракции типов и алгоритмов Шаблон алгоритма: template void Swap
a, T& b)
{ T c = a; a = b; b = c;}
Шаблон класса:
template class … Далее определение класса

Слайд 15

Параметры шаблонов, которые не являются типами

Вектора произвольной размерности с типом double или

Параметры шаблонов, которые не являются типами Вектора произвольной размерности с типом double
float, а может быть и int.
template class vect{
int n = N;
public:
T data[N];
int GetLen(){ return n; }
};

Слайд 16

Оператор определения типа

typedef vect Vector2D;
Теперь можно использовать
Vector2D v;
! Шаблоны, как

Оператор определения типа typedef vect Vector2D; Теперь можно использовать Vector2D v; !
и определения типа размещаются в заголовочных файлах!
Сам-по себе шаблон в результате компиляции не образует фрагмента кода. Он превращается в нужный метод или алгоритм на этапе компиляции вызывающей части кода!

Слайд 17

Промежуточный итог

Узнали особенности классов C++ :
Объявление объекта == создание. Не возникает =

Промежуточный итог Узнали особенности классов C++ : Объявление объекта == создание. Не
new …;
Объявление отделено от определения; В определении (cpp) указываем контекст (<Класс>::);
Более важна роль конструкторов; Конструктор “по умолчанию”, “инициализации”, …;
Структуры – те же классы. По умолчанию public (для совместимости с “C”);
При наследовании нужно указывать видимость предков. По умолчанию видимость private и методы предков не будут видны;
Шаблоны позволяют определять абстракции алгоритмов и структур данных. Располагаются шаблоны в заголовочных файлах. Параметрами шаблонов являются типы данных и конкретные значения.

Слайд 18

Контрольные вопросы

К чему приведет объявление класса в C++ без использования слова public?
Почему

Контрольные вопросы К чему приведет объявление класса в C++ без использования слова
в конце объявления класса ставится точка с запятой?
Определите время жизни объекта. Сформулируйте правило, по которому возникают и исчезают временные объекты в C++.
В чем различие между объектами в C++ и C# (.Net)?
Опишите время жизни объектов в C# (.Net)?
Что такое “конструктор инициализации”?
Опишите правила определения и использования параметров по умолчанию. (Где они указываются и почему, как они расположены в списке параметров, как могут опускаться при вызове)
В чем различие в C++ между struct и class?
Как будет исправлена дата при вызове Date d(0, 15, 2006), если конструктор реализован как в лекции? Какая дата будет задана при вызове Date d(2007)?
В чем различие в наследовании в C# и C++? (по лекции)
Где располагаются шаблоны?
Что означает в параметре шаблона слово class?

Слайд 19

Вызов функции и inline*

Вызов функции требует времени:
Вычислить и поместить в стек параметры
Запомнить

Вызов функции и inline* Вызов функции требует времени: Вычислить и поместить в
адрес возврата
Переключить стек и передать управление на функцию

Переключить стек и вернуть управление в вызывающий код
Частые вызовы коротких функций снижают эффективность выполнения программ.
Функцию можно пометить квалификатором inline. При этом, компилятор не будет генерировать эту функцию, а в местах вызова сгенерирует код, эквивалентный вызову.
inline int max(int a, int b){return a>b? a: b;}

Слайд 20

Переопределение операций Inline методы*

class Date {
int m_nYear;
int m_nMonth;
int m_nDay;
public:
Date();
Date(int year, int mon=1, int

Переопределение операций Inline методы* class Date { int m_nYear; int m_nMonth; int
day=1);
~Date() {}
bool operator < (const Date &d) const {
return m_nYear < d.m_nYear
|| (m_nYear == d.m_nYear && m_nMonth < d.m_nMonth)
|| (m_nYear == d.m_nYear && m_nMonth == d.m_nMonth && m_nDay < d.m_nDay);
}
int get_Year() const {return m_nYear;}
};
cout << (t < d) << “ “ << (d < e) << endl;

Слайд 21

“Динамические” объекты

char *s = new char[128];
Date *p = new Date();
Date *pv =

“Динамические” объекты char *s = new char[128]; Date *p = new Date();
new Date[5];
delete [] s;
delete p;
delete [] pv;
“Динамические” объекты создаются оператором new;
За удаление таких объектов отвечает программа!

Слайд 22

Указатели на объекты

При работе с динамическими объектами получаем указатели: Date *p = new

Указатели на объекты При работе с динамическими объектами получаем указатели: Date *p
Date();
Можно и как раньше, получить ссылку на объект (*p), и обращаться к доступным методам или данным через точку
int y = (*p).get_Year();
Но! Принято (и удобнее) использовать специальный синтаксис:
int y = p -> get_Year();

Слайд 23

Глобальные объекты

Правила:
Время жизни объектов ограничено блоком кода ({…})в котором они объявлены.
Глобальные объекты

Глобальные объекты Правила: Время жизни объектов ограничено блоком кода ({…})в котором они
объявляются вне всех блоков.
Это определяет время их жизни.
Но как сделать видимыми во всех модулях (cpp-файлах)?
Для этого, их объявления выносят в заголовочные h-файлы!

Слайд 24

Глобальные объекты*

Глобальный объект должен включаться в h-файл.
Что бы избежать создания его

Глобальные объекты* Глобальный объект должен включаться в h-файл. Что бы избежать создания
экземпляров во множестве объектных файлов (модулей) в языке введен квалификатор extern
H-файл ---------------------------
extern Date UnixBase;
Один из CPP-файлов ---------------------------
Date UnixBase(1970,1,1);
В других CPP, где включен h-файл можно использовать UnixBase!

Слайд 25

Статические поля*

Статические поля объявляются в классе с квалификатором static*
H-файл ---------------------------
class Test
{
public:
static int

Статические поля* Статические поля объявляются в классе с квалификатором static* H-файл ---------------------------
Count;
};
В CPP-файле ---------------------------
int Test :: Count = 0
В других CPP, где включен h-файл можно использовать Test :: Count!

Слайд 26

Промежуточный итог

Узнали:
Назначение и правила inline функций. Быстрее вызываются, определяем в h-файлах;
Переопределение операций

Промежуточный итог Узнали: Назначение и правила inline функций. Быстрее вызываются, определяем в
в C++; <тип >operator <операция> (<параметр>)…
Динамические объекты и указатели; new, delete, оператор ->;
Как правильно объявлять глобальные переменные и статические поля. Объявление в h с extern и размещение в cpp. Объявление static в классе и размещение в cpp;

Слайд 27

Контрольные вопросы

Что означает запись o.operator = (t)? Как ее можно эквивалентно записать

Контрольные вопросы Что означает запись o.operator = (t)? Как ее можно эквивалентно
иначе?
Переопределите операцию == для Date.
Что такое и зачем нужны inline функции и методы?
Как объявить inline метод в классе?
Что такое “динамические” объекты? Как они создаются? Уничтожаются?
Что означает запись: o->foo();? Что такое o? foo?
Опишите объявление и использование глобальных переменных в C++.
Как их объявить, что бы можно было использовать в разных модулях?
Как добиться того, что бы был создан только 1 уникальный экземпляр глобальной переменной?
Опишите правила объявления статических полей класса в C++.

Слайд 28

Виды конструкторов* Класс Str.

Класс для понимания роли конструкторов и деструкторов.
class Str {
char* m_pszText;
public:
Str

Виды конструкторов* Класс Str. Класс для понимания роли конструкторов и деструкторов. class
() //Конструктор “по умолчанию” (default)*
{m_pszText = new char[1]{0};}
~Str () { delete []m_pszText;}
};
Здесь деструктор обязателен!

1234

s

Слайд 29

Доработка Str*

Оператор преобразования типа (Str=>char*)
operator const char *()const {return m_pszText;}
После слова

Доработка Str* Оператор преобразования типа (Str=>char*) operator const char *()const {return m_pszText;}
operator следует определение типа.
В данном случае это const char * - константный указатель на символ (z-строка).
Теперь объекты Str можно применять везде, где допускается использовать z-строку!

Слайд 30

Конструктор инициализации для Str*

Str (const char * p)
{
if(p) {
m_pszText = new

Конструктор инициализации для Str* Str (const char * p) { if(p) {
char [strlen(p) + 1];
strcpy_s (m_pszText, strlen(p) + 1, p);
}
else
m_pszText = new char[1]{0};
}
Теперь можно:
Str s = “abc”;
Конструкторы с непустым списком параметров – конструкторы инициализации. Таких конструкторов может быть много.

Слайд 31

Варианты использования Str Неправильное копирование*

void Test1 (Str sz)
{}
Str Test2 () {
Str sz=

Варианты использования Str Неправильное копирование* void Test1 (Str sz) {} Str Test2
“123”;
return sz;
}
int main(){
Str s = “1234”;
Test1(s);
Str t = Test2();
}

1234

s

Создается копия s

sz

Копия разрушается

sz

1234

s

Исходный объект не валиден!

Слайд 32

Конструктор копирования*

Str (const Str &s) //Константная ссылка на объект
{
m_pszText = new char

Конструктор копирования* Str (const Str &s) //Константная ссылка на объект { m_pszText
[strlen(s.m_pszText) + 1];
strcpy_s (m_pszText,
strlen(s.m_pszText) + 1,
s.m_pszText);
}
Конструктор, у которого есть единственный параметр – константная ссылка на объект того же типа, называется конструктором копирования.
Он, если задан, будет вызываться во всех случаях создания копии объекта.

Слайд 33

Создание копии*

Теперь есть правила
Копирования
В результате получаем:
“Правильные” копии можно создавать и использовать

Создание копии* Теперь есть правила Копирования В результате получаем: “Правильные” копии можно
без ограничений!

1234

s

1234

sz

Слайд 34

Конструктор копирования Ловушка

Если нет конструктора копирования, то копирование заключается в копировании памяти (dummy

Конструктор копирования Ловушка Если нет конструктора копирования, то копирование заключается в копировании
constructor).
При этом, все переменные типа int, double … автоматически приобретут в копии то же значение, что и в оригинале!
Но, …!
если вы объявили собственный конструктор копирования, то это правило не действует! При копировании будут выполнены ТОЛЬКО ТЕ ДЕЙСТВИЯ, КОТОРЫЕ УКАЗАНЫ В КОНСТРУКТОРЕ КОПИИ!

Слайд 35

Конструктор копирования Ловушка. Пример.

class A{
public:
int Val;
A(int v=0) {Val=v;}
operator int&() const {return Val;}
};
A a(1),

Конструктор копирования Ловушка. Пример. class A{ public: int Val; A(int v=0) {Val=v;}
b(a);
cout<Добавим конструктор копии:
A(const A &a) {}
A a(1), b(a);
cout<
Во втором случае память не копировалась. Нужно обязательно в конструкторе копии
A(const A &a): Val(a.Val) {} или A(const A &a) {Val = a.Val;}

Слайд 36

Варианты использования Str Неправильное присваивание*

int main(){
Str s = “1234”, s1=“56”;
s = s1;
}
В результате

Варианты использования Str Неправильное присваивание* int main(){ Str s = “1234”, s1=“56”;
присваивания память s1 была скопирована в s:
Блок “1234” остался висеть;
Оба объекта “владеют” одним блоком.

1234

s

s1

56

1234

s

s1

56

Слайд 37

Операция присваивания*

const Str& operator = (const Str &s) //Константная ссылка на объект
{
if(&s

Операция присваивания* const Str& operator = (const Str &s) //Константная ссылка на
== this) return *this;
delete [] m_pszText; //Освобождаем текущие данные //Дальше просто копирование
m_pszText = new char [strlen(s.m_pszText) + 1];
strcpy_s (m_pszText,
strlen(s.m_pszText) + 1,
s.m_pszText);
return *this;
}
Теперь объекты класса Str можно без проблем присваивать друг другу.

Слайд 38

Еще о присваивании*

Имеется конструктор инициализации Str (const char* sz). Можем инициализировать объекты

Еще о присваивании* Имеется конструктор инициализации Str (const char* sz). Можем инициализировать
z-строкой/
Это удобно!
Можно ли присвоить уже созданному объекту z-строку (s = “911”)?
Да, можно! При этом, компилятор:
Создаст временный объект типа Str с начальным значением, равным z-строке;
Выполнить присваивание (есть оператор присваивания);
и разрушит временный объект.

Слайд 39

С объектами ВСЕ ПРОСТО!

Когда создаются копии объектов, а когда нет? Каково время

С объектами ВСЕ ПРОСТО! Когда создаются копии объектов, а когда нет? Каково
жизни объектов? Что происходит при присваивании? …
На многие вопросы можно ответить следуя правилу:
“Объекты классов ведут себя так же как и переменные встроенных типов”.
Время жизни определяется теми же правилами, что и для встроенных типов. Передача параметров, возникновение копий, определяется теми же правилами и т.п.

Слайд 40

Промежуточный итог

Узнали:
Виды конструкторов и зачем они нужны. Конструктор копии. Нужен, если в

Промежуточный итог Узнали: Виды конструкторов и зачем они нужны. Конструктор копии. Нужен,
классе используются динамические поля;
Как переопределить операцию преобразования типа; operator <тип> const()…
Разобрались, что происходит при присваивании; по умолчанию копируется память одного объекта в другой. Компилятор ищет возможность выполнить операцию;
Узнали как понять, что происходит с объектом. - “А что происходило бы с переменной встроенного типа?”;

Слайд 41

Контрольные вопросы

Перечислите виды конструкторов применяемых в C++.
Почему для Date не нужен деструктор

Контрольные вопросы Перечислите виды конструкторов применяемых в C++. Почему для Date не
и конструктор копии, а для Str нужны?
Почему в конструктор копии передают ссылку на объект, а не копию объекта?
Зачем при передаче ссылок и указателей применяется слово const?
Приведите примеры, когда копии объектов возникают без явного вызова конструктора.
Что в C++ методе означает слово this? Чем оно отличается от this в C#?
Что произойдет, если выполнить следующий код: Str s = “abcd”; s = “1234”;
Имеется соответствующий конструктор инициализации и оператор присваивания объектов Str.

Слайд 42

Ссылки и объекты в C#*

В C# Reference Type (Value Types похожи на

Ссылки и объекты в C#* В C# Reference Type (Value Types похожи
C++) это:
Всегда ссылка, но !
Ссылка в .Net – это самостоятельная переменная!
При копировании копируется ссылка, а не объект! Копирование объектов в .Net довольно сложная задача!

Слайд 43

Ссылки и объекты в C# Сравнение понятий

Ссылки и объекты в C# Сравнение понятий

Слайд 44

Строки стандартной библиотеки

#include
#include // Появился тип string.
using namespace std;

Строки стандартной библиотеки #include #include // Появился тип string. using namespace std;

string s;
cin >> s; // Читает слово
cout << s.length() << endl;
cout << s[0] << endl;
cout << (s + s) << endl;

Слайд 45

Строки стандартной библиотеки и консольный ввод

getline(cin, s); //Читает всю строку! cin>>s
while (!cin.eof()) // Закончится

Строки стандартной библиотеки и консольный ввод getline(cin, s); //Читает всю строку! cin>>s
по Ctrl+z
{
cout < cin >> s;
}
cout << "end of input" << endl;
cin.clear(); // Очистит Ctrl+z
cin >> s; // Теперь можно снова читать cin
Более полно будет рассмотрено в дальнейшем, при изучении stl.