- •Наследование классов, виртуальные функции
- •Теоретические сведения
- •Передача параметров в базовый класс
- •Типы наследования (уровни доступа к базовому классу)
- •Public – наследование
- •Использование методов
- •Private – наследование
- •Использование методов
- •Protected – наследование
- •Виртуальные функции и полиморфизм
- •Контрольные вопросы
- •Общие требования выполнения работы
Protected – наследование
Доступ к зоне 1 из зоны 2 (из методов производного класса к базовому классу)
public, protected, private - нет доступа к (только через методы класса)
Доступ к зоне 1 из зоны 3
при Protected-наследовании объекты производных классов имеют доступ к функциям базового класса
В остальном работа такая же как при private-наследовании.
Объявление в Base |
Доступ из Derived |
private |
private |
protected |
private |
public |
protected |
Добавим в класс itog метод для доступа к открытому полю age
class itog: protected student
{ . . .
int get_age ()
{return age;}
}; //-- конец определения произв. Класса
int _tmain(int argc, _TCHAR* argv[])
{ . . .
// доступ к Base -данным
cout<< "Итоги для: "<<T1.dget_name() ;
cout<<", адрес " <<T1.dget_adr();
cout<<", возраст: "<<T1.get_age();
// доступ к своим данным
cout<<"\nБаллы : \n по тестам "<<T1.get_test();
cout<<"\n по лабам "<<T1.get_lab();
cout<< "\n по БДЗ "<<T1.bdz;
cout<< endl;
. . .
}
Для закрепления теоретического материала в качестве примера разберем 3-х ступенчатую иерархию: точка->окружность->цилиндр
Класс «окружность» - производный от класса «точка», а класс «цилиндр» - производный от класса «окружность».
Для класса «цилиндр»:
«окружность» - это непосредственный базовый
«точка» - косвенный базовый класс.
#include "stdafx.h"
#include <iostream>
using namespace std;
//-------------определение класса point (точка)
class point
{ int x; // private-данные
int y;
public:
//конструктор
point(int xx=0,int yy=0):x(xx),y(yy){}
//конструктор копирования
point(point& p){x=p.x;y=p.y;}
// работа с закрытыми данными
// запись данных
void putx_y (int xx,int yy){x=xx; y=yy;}
// чтение данных
int getx(){return x;}
int gety(){return y;}
// печать данных (точка)
void show ()
{ cout<<x<<'\t'<<y<<endl;}
};//------- конец определения класса point
//----- определение класса circ (окружность)
class circ: public point
{// private-данные
int rad; // радиус
double p_circ; // длина окружности
double q_circ; //площадь круга
public:
// С помощью нескольких конструкторов можно задавать окружность
// по-разному
// задать окружность по координатам и радиусу
circ ( int x=0,int y=0, int r=3):point(x,y)
{rad=r;
p_circ=2*3.14*rad;
q_circ=3.14*rad*rad;
}
// задать окружность по точке и радиусу
// Этот конструктор передает параметр для конструктора копирования
// базового класса
circ ( point p, int r): point(p)
{ rad=r;
p_circ=2*3.14*rad;
q_circ=3.14*rad*rad;
}
// конструктор копирования
// Так как поля x,y – закрытые – доступ через методы класса
circ ( circ& c): point(c.getx(),c.gety())
{ rad=c.rad;
p_circ=2*3.14*rad;
q_circ=3.14*rad*rad;
}
// работа с закрытыми данными
int get_rad (){return rad;}
// печать данных (окружность)
void show ()
{ cout<<"circle : ";
cout<<"x="<<getx()<<'\t'<<"y="<<gety()<<'\t'<<"r="<<rad;
cout<<'\t'<<"p="<<p_circ<<'\t'<<"q="<<q_circ<<endl;}
};//----- конец определения класса circ
//----- определение класса Cylinder (цилиндр)
class Cylinder: public circ
{ // private-данные
int h; // высота
double s_Cyl; // площадь боковой поверхности
double v_Cyl; //объем цилиндра
public:
// конструкторы
// задать цилиндр по координатам, радиусу и высоте, данные передаются конструктору базового класса
Cylinder ( int x=0,int y=0, int r=3,int hh=5): circ(x,y,r)
{h=hh;
s_Cyl=2*3.14*get_rad()*h;
v_Cyl=3.14*get_rad()*get_rad()*h;
}
// задать цилиндр по окружности и высоте , данные передаются конструктору копирования
Cylinder ( circ c, int hh=5): circ(c)
{h=hh;
//закрытое поле rad в базовом классе circ – доступ через метод
s_Cyl=2*3.14*get_rad();
v_Cyl=3.14*get_rad()*get_rad();
}
// печать данных (цилиндр)
void show ()
{/* ко всем закрытым полям в базовом и косвенном базовом классе
есть доступ через методы класса, к своим полям (как закрытым, так и открытым) доступ прямой*/
cout<<endl<<"----Cylinder----"<<endl;
cout<<"x="<<getx()<<'\t'<<"y="<<gety();
cout<<'\t'<<"r="<<get_rad()<<'\t'<<"h="<<h;
cout<<'\t'<<"s="<<s_Cyl<<'\t'<<"v="<<v_Cyl<<endl;}
};//----- конец определения класса Cylinder
int _tmain(int argc, _TCHAR* argv[])
{point p1(1,2),p2; // создание 2-х точек
cout<<"-------p1-----"<<endl;
p1.show(); // печать информации о точке
cout<<"-------p2-----"<<endl;
p2.show();
p2.putx_y(2,3); // запись информации в объект p2
p2.show();
circ s1(1,2,3),s2(p2,6); // создать 2 объекта типа "окружность"
cout<<"-------s1-----"<<endl;
s1.show(); // печать информации об окружности
cout<<"-------s2-----"<<endl;
s2.show();
Cylinder c1,c2(0,10,15,50),c3(s2,9); // создать 3 объекта типа "цилиндр"
c1.show(); c2.show(); c3.show();
system("pause");
return 0;
}
Обратим внимание на функции show() в различных классах. Эти функции обеспечивают полиморфизм раннего связывания (на этапе трансляции программы).
Одинаковые по внешнему виду вызовы активизируют разные функции, но тип объекта, вызывающего функцию определяет из какого класса эта функция :
p2.show(); // печать точки
s1.show(); // печать окружности
c3.show(); // печать цилиндра
В объектно-ориентированных языках наряду с ранним связыванием реализован и полиморфизм позднего связывания (на этапе выполнения программы), этот динамический полимофизм реализуется с помощью механизма виртуальных функций.
