
- •220300 - Системы автоматизированного проектирования
- •Тема 2. Технологии программирования
- •Тема 2. Технология разработки крупных приложений
- •Структуры
- •Структуры и функции
- •Массивы структур
- •Поиск в массиве структур
- •Вложенность структур
- •Рекурсия
- •Алгоритм быстрой сортировки
- •Массивы структур и бинарные файлы
- •Динамические структуры данных
- •Линейные списки
- •Очереди
- •Контрольная работа
- •Объектно-ориентированное программирование. Классы
- •Конструкторы
- •Перегруженные конструкторы
- •Определение методов класса вне класса
- •Объекты, возвращаемые функцией (методом)
- •Структуры и классы
- •Классы и память
- •Статические данные класса
- •Константные методы
- •Деструкторы
- •Массивы и классы
- •Массивы объектов
- •Строки Строковый тип или стандартный класс string
- •Тип строк AnsiString
- •Перегрузка операций
- •Перегрузка арифметических операций
- •Перегрузка операций сравнения
- •Перегрузка операции приведения типа
- •Преобразования объектов в основные типы и наоборот
- •Преобразование объектов классов в объекты других классов
- •Наследование
- •Конструкторы производного класса
- •Перегрузка функций
- •Иерархия классов
- •Общее и частное наследование. Комбинации доступа
- •Множественное наследование
- •Включение. Классы в классах
- •Виртуальные и дружественные функции
- •Абстрактные классы и чистые виртуальные функции
- •Виртуальные деструкторы
- •Виртуальные базовые классы или устранение неоднозначности при множественном наследовании
- •Дружественные функции
- •Дружественные классы
- •Указатель this
- •Многофайловые программы
- •Распознавание нажатых клавиш
Перегрузка функций
Существует возможность определять для производного класса методы, имеющие такие же имена, как и у методов базового класса. В этом случае имеет место перегрузка функций. Такая возможность может понадобиться, если для объектов базового и производного классов в вашей программе используются одинаковые вызовы.
На одном из предыдущих занятий мы рассматривали программу, которая позволяла помещать числа в стек, а затем извлекать их. Допустим, что базовый класс не содержал в себе проверку на переполнение и при попытке отправить в стек слишком много чисел программа могла зависнуть по причине переполнения массива. При извлечении количества чисел, большего, чем находится в стеке, результат мог быть бессмысленным. Для исправления этих ошибок с помощью технологии наследования создадим производный класс Stack2.
class Stack {
protected:
enum { MAX = 3 }; // размер стека
int st[MAX]; // данные, хранящиеся в стеке
int top; // индекс последнего элемента в стеке
public:
Stack( ) // конструктор
{ top = -1; }
void push(int var) // помещение числа в стек
{ st[++top] = var; }
int pop( ) // извлечение числа из стека
{ return st[top--]; }
};
//---------------------------------------------------------------------------
class Stack2 : public Stack {
public:
void push(int var) { // помещение числа в стек
if (top > MAX-1) cout << "\nError: stack polon!"; // если стек полон, то ошибка
Stack::push (var); // если всё в порядке, то вызов функции push класса Stack
}
int pop( ) { // извлечение числа из стека
if (top < 0) cout << "\nError: stack pust!\n"; // если стек пуст, то ошибка
return Stack::pop( ); // если всё в порядке, то вызов функции pop класса Stack
}
};
//---------------------------------------------------------------------------
int main( ) {
Stack2 s1;
s1.push(11); // поместим в стек несколько чисел
s1.push(22);
s1.push(33);
cout << endl << s1.pop( ); // заберем числа из стека
cout << endl << s1.pop( );
cout << endl << s1.pop( );
cout << endl << s1.pop( ); // !!!, а данных-то больше нет
return 0; }
Как видно из данного примера, в классе Stack2 содержатся два метода push() и pop(), которые имеют те же имена, аргументы и возвращаемые значения, что и методы базового класса. В связи с этим возникает вопрос: Как компилятор поймёт, какой из методов вызвать? Существует правило: если один и тот же метод существует и в базовом, и в производном классе, то будет выполнен метод производного класса. Это правило справедливо только для объектов производного класса и не справедливо для объектов базового класса, поскольку им ничего не известно о производном классе, поэтому они всегда пользуются методами базового класса.
В нашем примере, в связи с тем что s1 – это объект производного класса Stack2, будет выполнен метод push() класса Stack2. Если стек полон, то метод пошлёт сообщение об ошибке, если – нет, то посредством строки Stack::push (var); вызывается метод push() базового класса Stack.