- •Лекции по Объектно-ориентированному программированию.
- •Классы.
- •Квалификаторы доступа.
- •Инициализация полей данных.
- •Операторы new и delete.
- •Перегруженные функции.
- •Конструктор копирования.
- •Статические компоненты класса.
- •Дружественные функции.
- •Перегрузка операций.
- •Наследование.
- •Производные классы. Доступ к базовым классам.
- •Возможны следующие варианты доступа:
- •Конструкторы и деструкторы в иерархии классов.
- •Виртуальные функции.
- •Virtual тип_возвр_знач-я имя_функции (параметры)
- •Потоки ввода / вывода.
- •Операции помещения и извлечения.
Конструкторы и деструкторы в иерархии классов.
Вызывается конструктор базового класса, а затем свой собственный (производный). Если конструктор базового класса требует параметры, то они включаются в список параметров конструктора производного класса. Их можно создать только при наследовании со спецификатором доступа public.
Student :: Student (char*n, int a, float d)
{strcpy (name, n);
age = a;
dohod = d;}
Stipendia_Studenta :: Stip_Stud (char*n, int a, float d, float r_s, int m) :
Student (name, age, dohod ) // конструктор произв. класса содержит параметры базового класса.
{ kol_month = m;
razmer_stip = r_s;}
В списке инициализации полей (после : ) в конструкторе производного класса указывается имя базового, его конструктору передаются необходимые параметры.
Так как деструкторы не имеют параметры, то при использовании объектов производных классов сначала вызывается деструктор производного класса, а потом базового класса.
Student :: ~ Student ( )
{cout << “ \ n Деструктор базового класса”; }
Виртуальные функции.
Они нужны для того, чтобы добавить новые методы или функции к унаследованным ранее или переопределить метод базового класса. Можно переопределить метод базового класса в производном. В этом случае при создании объекта производного класса и вызова для него какой-либо переопределенной функции произойдет вызов функции именно порожденного класса, а не базового. Если для вызова переопределенной функции использовать указатель или ссылки на объект базового класса, то произойдет вызов функции именно базового класса.
# include <iostream.h>
class base // базовый класс
{public : void print ( )
{cout<< ” \ n Это класс base”;}
};
class proizv : public base
{public : void print ( )
{cout<< ” \ n Это класс proizv”;}
};
void mane ( )
{base B, *bp = &B; // тип указ. base
proizv D, *dp = &D; // тип указ. proizv
base *p = &D; // тип указателя base
bp → print ( ); // base
dp → print ( ); // proizv
p → print ( ); // base
}
В последнем случае вызывается функция print ( ) базового класса, хотя указатель был р был настроен на объект производного класса D. Выбор нужной функции выполняется на этапе компиляции программы и определяется типом указателя, а не его значением.
Переопределенная функция вызывается в соответствии с классом указателя. Это раннее или статическое связывание.
Наибольшую гибкость дает метод позднего или динамичного связывания (с помощью виртуальных функций).
Virtual тип_возвр_знач-я имя_функции (параметры)
сlass base {public : virtual void print ( )
{------ // ------ // ------ } } ; и т.д. см. предыдущую.
Результатом
// base
// proizv
// priz
Виртуальная функция – это такая функция, которую можно объявить в базовом классе и переопределить в производном. Выбор того, какую функцию вызвать зависит от типа объекта, на который фактически, то есть в момент выполнения программы будет указывать указатель. Это чистый полиморфизм.
Вызов функции p→print ( ) – позднее связывание , то есть ссылка на функцию разрешается во время выполнения программы.
Абстрактные классы.
Существуют классы, которые выражают некую общую концепцию, которая отражает основной интерфейс для использования в производных классах. Это абстрактный класс. Его создают только для того, чтобы на его основе создавать другие классы. Создавать экземпляры объектов таких классов нельзя, поэтому их называют абстрактными.
С
ontrol


ButtonBase
ListControl

Button Check Radio List Combo
Box
Button
Box
Box
Чтобы класс сделать абстрактным, нужно объявить одну или более его функций чисто виртуальными.
virtual тип_возвр_значения имя_ф (параметры) = Ø;
Напр.: virtual void print ( ) = Ø;
Классы, имеющие хотя бы одну чисто виртуальную функцию, называют абстрактными, и не могут использоваться для создания объектов.
Можно использовать указатель абстрактного класса для работы с объектами производного класса.
Shape



area ( )
# ifndef SHAPE_H
# define SHAPE_H // Опред. абстрактн. кл.
class shape {protected : double param; // Т.к. поле param должно быть доступно в производном классе, поэтому мы используем protected – спец. доступа //
public : shape (double); // конструктор базового класса
virtual double area ( ) = Ø; // чисто виртуальная функция
}; // конец определения базового класса.
class circle : public shape { double radius;
public: circle (double);
double area ( ); }
class triangle : public shape { double hight, dlina;
public: triangle (double, double);
double area ( ); }
class rectangle : public shape
{ double
void print_area (shape*ptr) {cout<<”Пл = ”<<ptr→area ( )<<endl;} // функция
main ( )
{circle c (5);
triangle t (4,32);
rectangle r (2,7);
print_area (& c); // площадь круга
print_area (& t); // площадь треугольника
Функция print_area одинаково вызывает разные функции area, которые являются методами разных классов в зависимости от объекта, на который будет указывать параметр print_area.
Это означает, что компилятор не может однозначно определить ссылку на функцию во время компиляции метода area, а компоновщик, соответственно разрешить эту ссылку. Поэтому ссылка не разрешена до выполнения программы. Окончательное связывание с нужным методом производит система исполнения. Это – позднее связывание.
Множественное наследование.
class произв_кл : квалификатор_доступа Баз_класс1;
квал_доступа Баз_класс 2,…
Например:
Баз.кл.А Баз.кл.В
Поле а Поле b
Методы Методы

Произв.кл.С
Поле с
Методы
// Файл заголовочн. abc.h
# ifndef abc_h
# define abc_h
// 1 класс
class A {protected: int a;
public: A (int);
virtual void Show ( );}; // конец определения класса
// 2 класс
сlass B {protected: int b;
public: B (int);
virtual void Show ( );};
class C: public A, public B {
int c;
public: c (int, int, int);
void show ( ); };
// Файл реализации abc.cpp.
# include “abc.h”
# include<iostream.h>
A :: A (int n) : a(n) { }
B :: B (int n) : b(n) { }
C :: C (int k, int l, int m)
A(k), B(l), C(m) { }
void A :: show ( ) {cout<<”a = ”<<a<<endl;}
void B :: show ( ) {cout<<”b = ”<<b<<endl;}
void C :: show ( ) {cout<<”a = ”<<a<<”b = ”<<b<<”c = ”<<c<<endl;}
При работе с динамическими объектами этих классов можно использовать указатель любого базового класса для обращения к объектам производного класса с множественным наследованием от них.
// Демо-файл demo_abc.cpp
# include abc.h
void main ( )
{A *a = new A (1); // объекты базового класса
a → show ( );
delete a;
B *b = new B (2);
b → show ( );
delete b;
a = new C (3,4,5); // доступ к объектам произв.кл.
// производится с помощью указателя базового класса.
a → show ( );
delete a;
b = new C (6,7,8);
b → show ( );
delete b; }
Библиотека потоков языка СИ++ представляет собой набор классов для управления ввода/вывода. В сам язык СИ++ средства ввода/вывода не входят.
iostream.h
