
Tema_1_1_Klassy_i_obekty.ppt
- Количество слайдов: 33
Программирование на С++ Тема 1. Классы и объекты 16. 02. 2018 1
Синтаксис объявления класса в С++: class имя_класса { [private: ] //описание закрытых полей данных и методов [protected: ] //описание защищенных полей данных и методов [public: ] //описание открытых полей данных и методов }; 16. 02. 2018 2
Объектно-ориентированное программирование (ООП) стало доминирующей парадигмой программирования начиная с 80 -х годов, вытеснив процедурно-ориентированные способы программирования, разработанные в начале 70 -х годов. Традиционное структурное программирование (процедурно-ориентированное) заключается в разработке набора функций (алгоритмов) для решения поставленной задачи. Определив эти функции, программист должен задать подходящий способ хранения данных. Т. е. сначала решался вопрос, как манипулировать данными, а затем – какую структуру (тип данных) применить для организации этих данных. ООП изменило порядок этих действий на противоположный, поместив на первое место данные и сделав алгоритмы, предназначенные для их обработки, второстепенным вопросом. Язык С++ является объектно-ориентированным языком программирования, в то же время на нем можно писать и процедурно-ориентированные программы, так как С++ является расширением языка Си. Основными элементами объектно-ориентированной программы являются классы. Класс – это тип данных, по которому создается объект. Внутри класса находится описание данных и алгоритмов для работы с ними. Создание объекта на основе некоторого класса называется созданием экземпляра (instance) этого класса. Инкапсуляция (encapsulation) – это ключевое понятие при работе с объектами. Формально инкапсуляция – это объединение данных и операций над ними и сокрытие данных от пользователя объекта. Данные объекта называются полями , а функции, выполняющие операции над данными, – его методами. Значения полей объекта описывают его состояние, а методы его поведение. Применение любого метода к какому-нибудь объекту может изменить его состояние. Все объекты, являющиеся экземплярами одного и того же класса, ведут себя одинаково. 16. 02. 2018 3
Синтаксис объявления класса в С++: ключевое слово class, за которым следует открывающаяся фигурная скобка, после которой объявляются поля (переменные ) класса) и объявляются или определяются методы (функции) класса. Объявление класса завершается закрывающейся фигурной скобкой и точкой с запятой. Если в объявлении класса метод только объявляется, то он обязательно должен быть определен вне объявления класса. Если метод определяется вне объявления класса, то в заголовке, перед именем метода, указывается имя класса, к которому он относится, и операция доступа к области видимости (: : ). В объявлении класса также могут указываться ключевые слова private, public, protected, которые задают для клиентов класса степень доступа к полям и методам класса. Поля и методы, описанные в классе после ключевого слова private являются закрытыми, т. е. доступными только для методов этого класса и классов-друзей; По умолчанию все поля и методы класса считаются закрытыми (private). Поля и методы, описанные в классе после ключевого слова protected являются защищенными, т. е. доступными только для методов этого класса и классов-потомков. Поля и методы, описанные в классе после ключевого слова public являются открытыми, т. е. доступными для любых клиентов класса; Ключевое слово степени доступа (private, public, protected) применяется ко всем расположенным ниже полям и методам до тех пор, пока не встретиться следующее ключевое слово степени доступа. Это позволяет создавать в объявлении класса разделы для открытых, закрытых и защищенных полей и методов. 16. 02. 2018 4
Конструкторы и деструкторы Конструктор – метод класса, который автоматически вызывается после создания объекта. Деструктор – метод класса, который автоматически вызывается перед уничтожением объекта. Виды конструкторов: Конструкторы с параметрами; Конструкторы по умолчанию; Конструкторы копирования. 16. 02. 2018 5
Конструктор используется для инициализации полей объекта, а также для выделения памяти для динамических полей объекта (т. е. полей, имеющих тип указатель). Необходимость использования конструктора обусловлена тем, что переменные класса (поля данных) не могут непосредственно получать начальные значения в объявлении класса. Основные свойства конструктора 1. Имеет тоже имя, что и класс; 2. Для конструктора не указывается тип возвращаемого значения, т. к. конструктор не может возвращать значение; 3. Конструктор не наследуются. 4. Конструктор не может быть объявлен как const, virtual, static Конструкторы можно перегружать, для различных вариантов инициализации объектов класса. Деструктор используется для выполнения тех действий, которые необходимо выполнить перед уничтожением объекта, например, освобождает память, выделенную конструктором для динамических полей. • Имя деструктора совпадает с именем класса и начинается с символа тильда (~); Если деструктор не объявлен явно, он, как и конструктор, создается компилятором как пустой метод. Основные свойства деструктора: 1. Деструктор не имеет параметров; 2. Деструктор не может возвращать значение; 3. Деструктор не наследуется, кроме случая виртуального деструктора; 4. Деструктор не может быть объявлен как const, static; 5. Деструктор может быть объявлен как virtual. Поскольку деструктор не принимает никаких параметров, класс может иметь только один деструктор, перегрузка деструкторов запрещена. 16. 02. 2018 6
Основные варианты создания статического объекта имя_класса имя_объекта; имя_объекта(список параметров); Основные варианты создания динамического_объекта имя_класса *имя_указателя = new имя_класса; имя_класса *имя_указателя = new имя_класса (список параметров); Доступ к полям и методам, объявленным в секции public: имя_объекта. имя_поля имя_объекта. имя_метода() указатель_на_объект->имя_поля указатель_на_объект->имя_метода() 16. 02. 2018 7
На основе класса в программе создаются экземпляры этого класса (объекты). В зависимости от способа создания объекта (выделения памяти под объект) объекты могут быть статическими и динамическими. Под статические объекты память отводит компилятор, а под динамические объекты – программист с использованием операции динамического выделения памяти (new). При создании объекта класса пространство в памяти отводится только под поля объекта. Для методов память при создании объекта не резервируется. Каждый метод класса существует в памяти в единственном экземпляре и может использоваться каждым объектом класса. Если поля и методы объявлены в секции public, то к ним разрешен доступ за пределами класса любым функциям программы с использованием операций точка или стрелка. Для доступа за пределами класса к закрытым полям данных (объявленным в секции private)используют специальные методы доступа: Методы чтения (получения значения поля). Имена этих методов рекомендуют начинать с get; Методы записи (изменения значения поля). Имена этих методов рекомендуют начинать с set; 16. 02. 2018 8
Пример: #include <iostream> #include <conio. h> using namespace std; // объявление класса class Cat { private: int age; // возраст string name; // кличка public: Cat() {age = 1; }; //конструктор_1 Cat(string Name, int Age); //конструктор_2 ~Cat(){}; //деструктор int get. Age(); //возвращает возраст void set. Age(int Age); //устанавливает возраст void Meow(); }; 16. 02. 2018 9
// определение методов класса Cat: : Cat(string Name, int Age) {name = Name; age = Age; } int Cat: : get. Age(){ return age; } void Cat: : set. Age(int Age){ age = Age; } void Cat: : Meow() { cout << "n" << name << ": "; for (int i = 1; i <= age; i++) cout << "Meow "; } 16. 02. 2018 10
int main() { Cat 1; //статический объект Cat 2("Murzik", 3); //статический объект Cat * Cat 3 = new Cat; //динамический объект Cat * Cat 4 = new Cat("Pushok", 4); Cat 1. Meow(); Cat 2. Meow(); Cat 3 ->Meow(); Cat 4 ->Meow(); // Cat 1. age = 5; Ошибка!!! Cat 2. set. Age(4); // Правильно!!! Cat 4 ->set. Age(5); cout << "n"; Cat 2. Meow(); Cat 4 ->Meow(); delete Cat 3; delete Cat 4; } 16. 02. 2018 11
Если в классе отсутствует конструктор, то компилятором автоматически создается конструктор по умолчанию (конструктор без параметров). Автоматически созданный конструктор не выполняет инициализацию полей объекта класса. Если класс имеет конструктор с параметрами, то конструктор без параметров автоматически не создается, поэтому, если необходимо создавать объект без его инициализации, то конструктор без параметров необходимо создавать явно (т. е. перегрузить конструктор с параметрами). Конструктор может содержать значения параметров по умолчанию. Задание в конструкторе значений параметров по умолчанию позволяет гарантировать, что объект будет находиться в непротиворечивом состоянии, даже если в вызове конструктора не указаны никакие значения. 16. 02. 2018 12
Массивы объектов Cat Family 1[500]; //массив из 500 объектов класса Cat * Family 2[500]; //массив из 500 указателей на //объекты класса Cat * Family 3; //указатель на массив из 500 // объектов класса Cat Family 3 = new Cat[500]; //массив из 500 объектов // класса Cat 16. 02. 2018 13
Пример. int main() { Cat Family 1[5]; // статический массив объектов for (int i=0; i < 5; i++) Family 1[i]. set. Age(2*i+1); for (int i=0; i < 5; i++) cout <<" Cat N "<< i+1 << " is a cat who is " << Family 1[i]. get. Age()<<" years old. n"; } 16. 02. 2018 14
Пример. int main() { Cat * Family 2[5]; // массив указателей for(int i=0; i < 5; i++) { Family 2[i] = new Cat; Family 2[i]-> set. Age(2*i+3); } for(int i=0; i < 5; i++) cout <<" Cat N " << i+1 <<" is a cat who is " << Family 2[i]->get. Age()<<" years old. n"; for (int i=0; i<5; i++) { delete Family 2[i]; Family 2[i] = NULL; } } 15
Пример. int main() { Cat * Family 3 = new Cat[5]; for (int i=0; i < 5; i++) Family 3[i]. set. Age(2*i+2); for (int i=0; i < 5; i++) cout << "Cat N " << i+1 <<" is a cat who is " << Family 3[i]. get. Age() <<" years old. n"; delete []Family 3; } 16. 02. 2018 16
Присваивание объектов #include <iostream> using namespace std; class My. Cat // объявление класса мой кот { private: unsigned int its. Age; // возраст кота public: My. Cat(int initial. Age){its. Age = initial. Age; } My. Cat(){its. Age = 1; } //конструктор по умолчанию ~My. Cat(){}; //деструктор int Get. Age()const; // возвращает возраст void Set. Age(int age); //устанавливает возраст void Meow(); }; // определение (реализация) методов int My. Cat: : Get. Age()const { return its. Age; } void My. Cat: : Set. Age(int age) {its. Age = age; } void My. Cat: : Meow() { cout << "Meow. n"; } 17
class Your. Cat // объявление класса ваш кот { private: unsigned int its. Age; //возраст кота public: Your. Cat(int initial. Age){its. Age=initial. Age; } Your. Cat(){its. Age=1; }//конструктор по умолчанию ~Your. Cat(){}; //деструктор int Get. Age()const; // возвращает возраст void Set. Age(int age); //устанавливает возраст void Meow(); }; // определение (реализация) методов int Your. Cat: : Get. Age()const { return its. Age; } void Your. Cat: : Set. Age(int age){its. Age = age; } void Your. Cat: : Meow(){cout << "Meow. n"; } 18
int main() { My. Cat 1(7), Cat 2; Your. Cat 3; cout << "Cat 1 is a cat who is " << Cat 1. Get. Age() <<" years old. n"; cout << "Cat 2 is a cat who is " << Cat 2. Get. Age() <<" years old. nn"; Cat 2 = Cat 1; cout << "Cat 1 is a cat who is " << Cat 1. Get. Age() <<" years old. n"; cout << "Cat 2 is a cat who is " << Cat 2. Get. Age() <<" years old. n"; cout << "n"; // Cat 3 = Cat 1; // Ошибка !!! } 19
Ø Ø Один объект можно присвоить другому объекту, если оба они одинакового типа. По умолчанию, когда объект А присваивается объекту В, происходит побитовое копирование всех данных-элементов (значений полей) А в данные-элементы ( поля) В. Объекты А и В при этом приобретают одинаковые значения полей, оставаясь совершенно независимыми. Присваивать можно лишь объекты одного типа (т. е. с одним именем типа), а не типов, одинаковых физически. 16. 02. 2018 20
Конструктор копирования Варианты вызова конструктора копирования: Any. Class ob 2 = ob 1; //ob 1 явно инициализирует ob 2 Any. Fn 1(ob 1); //ob 1 передается в качестве параметра ob 2 = Any. Fn 1(ob 1); //ob 2 получает значение возвра// щаемого объекта Синтаксис конструктора копирования: имя_класса (const имя_класса &obj) { тело_конструктора } obj – ссылка на объект, используемый инициализации другого объекта для 21
Конструктор копирования представляет собой одну из наиболее важных форм перегрузки конструктора, которая в состоянии решить одну из проблем, которая возникает при побитовом копировании объектов. Конструктор копирования вызывается всякий раз, когда создается новый объект, и инициализируется существующим объектом такого же типа. При явном задании конструктора копирования этот процесс становиться управляемым. В С++ четко разделяются два типа ситуаций, при которых значение одного объекта присваивается другому: присваивание; инициализация. Конструктор копирования используется только при инициализации. Конструктор копирования никогда не участвует в процессе присваивания и никак не влияет на него. Инициализация имеет место в трех случаях: ◦ Когда в операторе объявления один объект используется для инициализации другого; ◦ При передаче объекта в качестве параметра функции; ◦ При создании временного объекта для возврата значения из функции. Конструктор копирования, заданный по умолчанию (неявно) , выполняет поэлементное копирование нестатических элементов. При этом выполняется копирование по значению (побитовое копирование). В результате такого копирования могут возникнуть проблемы, например, при побитовом копировании объекта, содержащего в качестве поля динамический массив (будут скопированы не сами элементы массива, а его адрес). Для решения подобных проблем применяют явно заданные конструкторы копирования. Следует помнить, что передача объекта в функцию по ссылке предотвращает вызов конструктора копирования. Это позволяет сберечь время, необходимое для его вызова и сэкономить память, используемую для хранения нового объекта. 16. 02. 2018 22
Пример: #include <string. h> #include <iostream> using namespace std; // объявление класса class Cat { private: int age; // возраст char* name; // кличка public: Cat() {age = 1; }; //конструктор_1 Cat(char* Name, int Age); //конструктор_2 ~Cat(){delete []name; } //деструктор Cat(const Cat &c); //конструктор_3 int get. Age(); //возвращает возраст void set. Age(int Age); //устанавливает возраст void Meow(); }; 23
// определение методов Cat: : Cat( char* Name, int Age) { int leng=strlen(Name); //выч. длины имени name=new char [leng+1]; //выделяем память strcpy(name, Name); //копируем имя age = Age; } int Cat: : get. Age(){ return age; } void Cat: : set. Age(int Age){ age = Age; } void Cat: : Meow() { cout << "n"<< name << ": "; for (int i = 1; i <= age; i++) cout << "Meow "; } 24
//определение конструктора копирования Cat: : Cat(const Cat &c) {int leng=strlen(c. name); //выч-е длины имени name=new char[leng+1]; //выд-е памяти для копии strcpy(name, c. name); //копируем имя age=c. age; //копируем возраст } int main() { Cat 2("Murzik", 3); //статический объект Cat 1 = Cat 2; Cat 1. Meow(); } 25
Интерфейс и реализация класса. Указатель this Ø Пример: // Файл cat. h // объявление класса #ifndef CAT_H_ #define CAT_H_ class Cat { private: int age; // возраст string name; // кличка public: Cat() {age = 1; }; //конструктор_1 Cat(string Name, int Age); //конструктор_2 ~Cat(){}; //деструктор int get. Age(); //возвращает возраст void set. Age(int Age); //устанавливает возраст void Meow(); }; #endif 26
#include "cat. h" #include <iostream> using namespace std; // определение методов класса Cat: : Cat(string Name, int Age) {name = Name; age = Age; } int Cat: : get. Age(){ return this->age; } void Cat: : set. Age(int Age){ this->age = Age; } void Cat: : Meow() { cout << "n" << name << ": "; for (int i = 1; i <= age; i++) cout << "Meow "; } 16. 02. 2018 27
//Файл main. cpp #include "cat. h" #include <iostream> using namespace std; int main() { Cat 1; //статический объект Cat 2("Murzik", 3); //статический объект Cat * Cat 3 = new Cat; //динамический объект Cat * Cat 4 = new Cat("Pushok", 4); Cat 1. Meow(); Cat 2. Meow(); Cat 3 ->Meow(); Cat 4 ->Meow(); Cat 2. set. Age(4); Cat 4 ->set. Age(5); cout << "n"; Cat 2. Meow(); Cat 4 ->Meow(); delete Cat 3; delete Cat 4; } 16. 02. 2018 28
Ø Описание класса обычно располагается в отдельном модуле. Ø Модуль – это часть программы, которая может компилироваться отдельно. Если рассматривать структуру модуля, то модуль состоит из двух частей: интерфейс и реализация. В С++ и интерфейсная часть модуля и реализация размещаются в отдельных файлах. Интерфейсная часть модуля – в заголовочном файле (. h), а реализация модуля в файле реализации (. cpp). Ø Обычно модуль содержит объявление и определение только одного класса, но компилятор не сочтет ошибкой и наличие нескольких классов. Ø Объявление класса (Например, объявление класса Cat) обычно размещается в заголовочном файле модуля (cat. h) и называется интерфейсом класса, поскольку оно сообщает пользователю, как взаимодействовать с классом. Ø Определения методов класса (Например, определения методов класса Cat) обычно размещается в файле реализации модуля (cat. cpp) и называется реализацией класса. Причем заголовочный файл подключают в файл реализации с помощью директивы #include (Например, #include "cat. h“). Ø Файл реализации класса (Например, файл cat. cpp) всегда нужно добавлять в проект программы, которая является клиентом класса. А в саму программу включать интерфейс класса (Например, файл cat. h). Ø Каждый метод класса имеет скрытый (неявный) параметр – указатель this. Этот указатель содержит адрес текущего объекта, который вызывает метод. Ø Обычно указатель this не применяется для доступа к полям объекта из методов самого объекта. Но при желании для явного обращении можно применить и указатель this. В примере это сделано в демонстрационных целях. Ø Пример практического применения указателя this будет рассмотрен при рассмотрении темы перегрузка операций. 16. 02. 2018 29
16. 02. 2018 30
16. 02. 2018 31
16. 02. 2018 32
Контрольные вопросы 1. Понятие класса и объекта в С++. Понятие инкапсуляции. 2. Как организуется доступ к закрытым и открытым элементам класса? 3. Понятие, назначение и основные свойства конструкторов и деструкторов. Виды конструкторов. 4. Назовите способы создания массива объектов, приведите примеры. 5. Понятие интерфейса и реализации класса. 6. Указатель this, его назначение и применение. 33
Tema_1_1_Klassy_i_obekty.ppt