Слайд 1Тема: Наследование
Роль наследования в ООП
Проблемы родственных типов
Наследование – разрешение проблем
Слайд 2Родственные типы
В процессе структуризации типов в объектно-ориентированной программы возникают группы
родственных, но не одинаковых классов
Пример – оконный интерфейс
Text_Window – вывод
текста на экран
clear – очистка содержимого окна
move_cursor – изменение текущей позиции в окне
add – добавление информации в окно
move – перемещение окна
change_size – изменение размера окна
Слайд 3Другие окна
Shell_Window – вывод сообщений операционной системы
clear, move_cursor, add, move,
change_size
execute – выполнение команды ОС
Input_Window – окно диалога с пользователя
clear,
move_cursor, add, move, change_size
read_input – ввод данных пользователя
Слайд 4Пути реализации
Три независимых класса
Проблемы:
дублирование кода
при разработке классов
при использовании классов
нельзя писать
полиморфный код
Один универсальный класс
Проблемы:
модификация отлаженного кода
возрастает логическая сложность методов
нельзя использовать
контроль типов (писать код, допустимый только для одного типа окон)
Слайд 6
class Text_Window {
public:
void clear();
void move_cursor(const
Point&);
void add(char);
void add(const String&);
void
move(const Point&);
void change_size(const Point&);
private:
// свойства
};
class Shell_Window {
public:
void clear();
void move_cursor(const Point&);
void add(char);
void add(const String&);
void move(const Point&);
void change_size(const Point&);
void execute(const String&);
private:
// свойства
};
class Input_Window {
public:
void clear();
void move_cursor(const Point&);
void add(char);
void add(const String&);
void move(const Point&);
String read_input();
private:
// свойства
};
Слайд 7Дублирование кода методов независимых классов
void Text_Window::clear() { // очистить окно
Text_Window }
void Shell_Window::clear() { // очистить окно Shell_Window }
void Input_Window::clear()
{ // очистить окно Input_Window }
void Text_Window::change_size(const Poin& new_size) {
// изменить размер окна Text_Window
}
void Shell_Window::change_size(const Poin& new_size) {
// изменить размер окна Shell_Window
}
void Input_Window::change_size(const Poin& new_size) {
// изменить размер окна Input_Window
}
Слайд 8Полиморфизм: функция blank
#include “window.h”
// функция использует только общие
// для всех
видов окон методы
// и могла бы быть полиморфной
void blank( Text_Window&
w ) {
w.clear();
w.move_cursor( Point(0,0) );
w.add( “This window was blank” );
}
Слайд 10
enum id_window { text, input, shell };
class Window {
public:
Window(
id_window );
id_window kind_of_window();
void clear();
void move_cursor(const Point&);
void add(char);
void add(const String&);
void move(const Point&);
void change_size(const Point&);
void execute(const String&);
String read_input();
private:
id_window id;
// свойства, общие
// для всех окон
// специализированные данные
union {
// данные для Text_Window
// данные для Shell_Window
// данные для Input_Window
} special_data;
};
Слайд 11Сложность кода методов общего класса
void Window::clear() { // очистить любой
вид окна }
void Window::change_size(const Poin& new_size) {
switch ( id
) {
case text : // изменить размер окна Text_Window
break;
case shell : // изменить размер окна Shell_Window
break;
case input : // изменить размер окна Input_Window
break;
}
}
Слайд 12Сложность кода методов …
String Window::read_input() {
switch ( id )
{
case input : // считываем и возвращаем
строку
break;
default :
fprintf( stderr, “Wrong kind of window \n”); exit(1);
}
}
Слайд 13Отсутствие строгой типизации
// функция может работать только с окном вида
Input_Window
int yes_or_no(Window& w, const String& question)
{
String answer ;
do
{
w.clear();
w.move_cursor( Point(0,0) );
w.add(question);
answer = w.read_input() ;
} while ( answer != “yes” && answer != “no” );
return answer == “yes” ;
}
Слайд 15Наследование позволяет
Избежать дублирование кода при разработке классов
Модифицировать классы даже без
доступа к исходным текстам методов и без изменения уже отлаженного
кода
Писать полиморфный код
Использовать контроль типов (писать код, допустимый только для окон одного вида)
Избежать значительного усложнения методов
Слайд 16Создание базового класса
Собрать свойства и методы, общие для всех потомков
Базовый
класс ничего не знает о своих потомках
Производный класс наследует все
члены базового класса
Производный класс может определять дополнительные свойства и методы
Производный класс может переопределять унаследованные свойства и методы
Класс может иметь несколько предков
Слайд 17Базовый класс Window
class Window {
public:
Window( const Point& upleft, const
Point& size,
const String& title);
~Window( );
void move(const
Point& new_upleft);
Point upper_left() const;
Point lower_right() const;
Point size() const;
void change_size(const Point& new_size);
// если новый размер меньше минимального, то окно
// уменьшается только до минимального размера
Слайд 18Базовый класс Window (продолжение)
int move_cursor(const Point& new_position);
Point cursor() const;
Display_char character()
const ; // символ под курсором
String line() const
; // строка, на которой находится курсор
void add(Display_char ch); // поместить символ в окно
void add(const String& str); // помещает строку в окно
void clear();
void scroll_up();
void scroll_down();
private:
// данные для класса Window
};
Слайд 19Использование объектов Window
#include “window.h”
#include “dos.h” // для sleep
void main( int, char*[
] ) {
Window w(Point(10,2), Point(40,6), “test window”);
sleep(2) ;
w.move_cursor(Point(0,1)) ;
w.add(“This
is a test”) ;
sleep(2) ;
w.clear() ;
w.add(“It disappear at \n”) ;
w.add(“the end of main().”) ;
sleep(2) ;
}
Слайд 20Класс Shell_Window
Такой же, как и Window, НО
имеет дополнительный метод execute
размер
окна не менее 40 х 3
заголовок отмечен символом “|”
Слайд 21Shell_Window ? Window
#include “window.h”
extern const Point min_sw_size ; // 40
x 3
class Shell_Window : public Window {
public:
Shell_Window(const
Point& upleft,
const Point& size, const String& title);
int execute(const String& command);
// выполняет команду, помещает результат в окно,
// возвращает код выхода или –1 если неудача
void change_size(const Point& new_size);
// если новый размер меньше минимального, то окно
// уменьшается только до минимального размера
}
Слайд 22Методы производного класса Shell_Window
#include “window.h”
#include “stdio.h”
int Shell_Window::execute(const String& command) {
FILE* out = fopen(“tmp”,w+) ;
if(
out == NULL ) return -1;
system( command + “ > tmp ” );
char buf [80] ;
while( fgets( buf, 80, out ) != 0 )
add(buf); // помещаем текст в окно
return fclose(out) ;
}
Слайд 23Использование методов производного класса
#include “window.h”
#include // для sleep
void main(
int, char*[ ] ) {
Window w(Point(10,16), Point(40,6),
“A window”);
Shell_Window sw(Point(1,1),
Point(50,10),
“A shell window”);
w.add(“This is a window”) ;
sleep(2) ;
sw.add(“Files: \n”) ;
sw.execute(“dir”) ;
sleep(2) ;
}
Слайд 24Перегрузка методов производного класса
#include “window.h”
const Point min_sw_size(40,3);
void Shell_Window::change_size(const Point& new_size)
{
Window::change_size(max(new_size, min_sw_size)) ;
}
Слайд 25Использование перегруженных методов
#include “window.h”
#include “dos.h” // для sleep
void main( int, char*[
] ) {
Window w(Point(10,16), Point(40,6),
“A window”);
Shell_Window sw(Point(1,1), Point(50,10),
“A shell
window”);
sleep(2) ;
sw.change_size( Point(2,2) ) ;
w.change_size( Point(2,2) ) ;
sleep(2) ;
}
Слайд 26Конструкторы производного класса
#include “window.h”
const Point min_sw_size(40,3);
Shell_Window::Shell_Window(const Point& upleft , const
Point& size , const String& title ) : Window(upleft ,
max(size, min_sw_size),
“| ”+title+ “ |” ) { }
Слайд 27Конструкторы производного класса
При создании объекта производного класса сперва вызывается конструктор
базового класса, а затем конструктор производного класса, НО конструктор базового
класса может передавать параметры конструктору производного класса
Если базовый класс не имеет конструктора, то конструктор производного класса не должен передавать параметры
Если базовый класс имеет конструктор по умолчанию, то конструктор производного класса может не передавать параметры
Слайд 28РЕЗЮМЕ
Базовый класс объединяет общие («семейные») операции и методы
Базовый класс не
знает о своих потомках
Производный класс наследует все члены базового класса
Производный
класс не имеет доступа в закрытую часть предка
Производный класс может переопределять унаследованные свойства и методы
Производный класс может определять свои свойства и методы
Конструктор производного класса управляет конструктором базового