Спадкування класів в C ++
- Створення базового класу
- Спадкування від базового класу
- Конструктор базового класу
- Створення об'єкта класу student
- Створення класу-спадкоємця teacher
- Створення об'єкта класу teacher
- Коли потрібно використовувати конструктор
Спадкування дозволяє уникнути дублювання зайвого коду при написанні класів . Нехай в базі даних ВНЗ а повинна зберігатися інформація про всіх студентів та викладачів. Представляти всі дані в одному класі не вийде, оскільки для викладачів нам знадобиться зберігати дані, які для студента не застосовні, і навпаки.
Створення базового класу
Для вирішення цього завдання створимо базовий клас human, який буде описувати модель людини. У ньому будуть зберігатися ім'я, прізвище та по батькові.
Створіть файл human.h:
// human.h #ifndef HUMAN_H_INCLUDED #define HUMAN_H_INCLUDED #include <string> #include <sstream> class human {public: // Конструктор класу human human (std :: string last_name, std :: string name, std :: string second_name ) {this-> last_name = last_name; this-> name = name; this-> second_name = second_name; } // Отримання ПІБ людини std :: string get_full_name () {std :: ostringstream full_name; full_name << this-> last_name << "" << this-> name << "" << this-> second_name; return full_name.str (); } Private: std :: string name; // ім'я std :: string last_name; // прізвище std :: string second_name; // батькові}; #endif // HUMAN_H_INCLUDED
Спадкування від базового класу
Тепер створіть новий клас student, який буде спадкоємцем класу human. Помістіть його в файл student.h.
// student.h #ifndef STUDENT_H_INCLUDED #define STUDENT_H_INCLUDED #include "human.h" #include <string> #include <vector> class student: public human {public: // Конструктор класу Student student (std :: string last_name, std :: string name, std :: string second_name, std :: vector <int> scores): human (last_name, name, second_name) {this-> scores = scores; } // Отримання середнього бала студента float get_average_score () {// Загальна кількість оцінок unsigned int count_scores = this-> scores.size (); // Сума всіх оцінок студента unsigned int sum_scores = 0; // Середній бал float average_score; for (unsigned int i = 0; i <count_scores; ++ i) {sum_scores + = this-> scores [i]; } Average_score = (float) sum_scores / (float) count_scores; return average_score; } Private: // Оцінки студента std :: vector <int> scores; }; #endif // STUDENT_H_INCLUDED
Функція get_average_score обчислює середнє арифметичне всіх оцінок студента. Усе публічні властивості і методи класу human будуть доступні в класі student.
Конструктор базового класу
Для того, щоб ініціалізувати конструктор батьківського класу (в нашому випадку - це збереження імені, прізвища та по батькові учня), використовується наступний синтаксис:
// Конструктор класу Student student (// аргументи конструктора поточного класу): human (// ініціалізація конструктора батьківського класу) {// ініціалізація конструктора поточного класу}
У конструктор класу human ми передаємо ініціали людини, які зберігаються в екземплярі класу. Для класу students, нам необхідно задати ще і список оцінок студента. Тому конструктор students приймає всі аргументи конструктора базового класу, а також додаткові аргументи для розширення функціоналу:
// Конструктор класу Student student (std :: string last_name, std :: string name, std :: string second_name, std :: vector <int> scores): human (last_name, name, second_name) {this-> scores = scores ; }
Список оцінок студента зберігається в векторі .
Створення об'єкта класу student
Реалізуємо призначений для користувача інтерфейс для роботи з класом student.
// main.cpp #include <iostream> #include <vector> #include "human.h" #include "student.h" int main (int argc, char * argv []) {// Оцінки студента std :: vector <int> scores; // Додавання оцінок студента в вектор scores.push_back (5); scores.push_back (3); scores.push_back (2); scores.push_back (2); scores.push_back (5); scores.push_back (3); scores.push_back (3); scores.push_back (3); scores.push_back (3); // Створення об'єкта класу student student * stud = new student ( "Петров", "Іван", "Олексійович", scores); // Висновок повного імені студента (використовується успадкований метод класу human) std :: cout << stud-> get_full_name () << std :: endl; // Висновок середнього бала студента std :: cout << "Середній бал:" << stud-> get_average_score () << std :: endl; return 0; }
У цьому прикладі ми написали програму, яка створює об'єкт класу student, зберігаючи в ньому його ім'я, прізвище, по батькові та список оцінок.
Після ініціалізації об'єкта, відбувається висновок повного імені студента за допомогою функції get_full_name. Ця функція була успадкована від базового класу human.
Потім програма вичісліяет середній бал студента і виводить його на екран. Цим займається функція get_average_score, яку ми описали всередині класу student.
Ми реалізували частину функціоналу для нашої бази даних інституту (я звичайно перебільшую, коли оперую настільки серйозними висловлюваннями про справжню базу даних :)
Створення класу-спадкоємця teacher
Потрібно створити ще один клас, в якому будуть зберігатися дані викладачів. Дамо йому назву - teacher. Як ви вже зрозуміли, ми не будемо описувати всі методи цього класу з нуля, а просто успадкуємо його від класу human. Тоді, не потрібно буде реалізовувати зберігання імені, прізвища та по батькові препода. Це вже є в базовому класі human.
Створіть файл teacher.h:
// teacher.h #ifndef TEACHER_H_INCLUDED #define TEACHER_H_INCLUDED #include "human.h" #include <string> class teacher: public human {// Конструктор класу teacher public: teacher (std :: string last_name, std :: string name, std :: string second_name, // Кількість навчальних годин за семетр у викладача unsigned int work_time): human (last_name, name, second_name) {this-> work_time = work_time; } // Отримання кількості навчальних годин unsigned int get_work_time () {return this-> work_time; } Private: // Навчальні години unsigned int work_time; }; #endif // TEACHER_H_INCLUDED
У класу teacher з'явилося нове властивість - кількість навчальних годин, відведений викладачу на одиницю часу (семестр). Весь інший функціонал успадковується від базового класу human. Якби ми писали все з нуля, то однакового коду б вийшло в рази більше, і його підтримка ускладнилася б на порядок.
Створення об'єкта класу teacher
Змінимо вміст файлу main.cpp, щоб перевірити роботу класу teacher.
#include <iostream> #include "human.h" #include "teacher.h" int main (int argc, char * argv []) {// Кількість навчальних годин викладача unsigned int teacher_work_time = 40; teacher * tch = new teacher ( "Васильків", "Петро", "Сергійович", teacher_work_time); std :: cout << tch-> get_full_name () << std :: endl; std :: cout << "Кількість годин:" << tch-> get_work_time () << std :: endl; return 0; }
Якщо збірка програми пройшла без помилок, то результат роботи програми буде таким:
Можна таким же чином створити клас, в якому будуть зберігатися дані обслуговуючого персоналу або керівного складу. Спадкування використовують, коли у кожної групи об'єктів є загальні параметри, але для кожної з цих груп потрібно зберігати більш кастомниє дані.
Також, ми можемо створити клас, який буде описуючи студента заочної форми навчання. Його ми успадкували б від класу student, додавши будь-які додаткові дані.
В клас human можна додати ще більше властивостей, які будуть описувати дані, наявні у будь-якої людини. Наприклад, номер паспорта, дату народження, прописку та місце проживання.
Подібний підхід дозволяє в рази зменшити дублювання коду в реальних проектах, і вблагати його підтримку.
Коли потрібно використовувати конструктор
Якщо у класу багато властивостей - їх зовсім не обов'язково ставити в конструкторі. Для збереження окремих властивостей класу використовують set-функції. Наприклад, для збереження номера паспорта, можна створити публічний метод set_passport_number (std :: string number), який буде приймати значення властивості і зберігати його в об'єкті, через змінну this.
Наступний урок - перевантаження функцій в C ++.