189.17K
Категория: ПрограммированиеПрограммирование

Наследование в программировании

1.

НАСЛЕДОВАНИЕ
Ключи доступа : private, protected, public
class имя : [private | protected | public]
базовый_класс {тело_класса};

2.

НАСЛЕДОВАНИЕ
class A{//};
class B{…};
class C{…};
class D: A, protected B, public C {…};
// по умолчанию private для класса
// для структуры public

3.

НАСЛЕДОВАНИЕ
Доступ в
Ключи доступа
Спецификатор в производном классе
базовом классе
private
Private
Нет
Protected
Private
public
private
protected
Provate
Нет
Protected
Protected
public
protected
public
private
Нет
Protected
Protected
public
public

4.

НАСЛЕДОВАНИЕ
class Base{
….
public: void f();
};
class Derived : private Base{

public: Base:: void f();
};

5.

НАСЛЕДОВАНИЕ
#include<iostream>
using namespace std;
class base{
int x;
public: void set_x( int n){ x=n;}
void show_x(){ cout< < x< <endl;
};

6.

НАСЛЕДОВАНИЕ
class derived : public base {
int y;
public: void set_y( int n){ y=n;}
void show_y(){ cout< < y< <endl;
};

7.

НАСЛЕДОВАНИЕ
int main()
{
derived ob;
ob.set_x(10);
ob.set_y(20);
ob.show_x();
ob.show_y();
return 0;
}

8.

НАСЛЕДОВАНИЕ
class derived : public base {
int y;
public: void set_y( int n){ y=n;}
void show_y(){ cout< < y< <endl;
void show_sum(){ cout< < x+y < <endl;}
};

9.

НАСЛЕДОВАНИЕ
class derived : private base {
int y;
public: void set_y( int n){ y=n;}
void show_y(){ cout< < y< <endl;
};

10.

НАСЛЕДОВАНИЕ
int main(){
derived ob;
// ob.set_x(10);
ob.set_y(20);
// ob.show_x();
ob.show_y();
base ob1;
ob1.set_x(1);
return 0; }

11.

НАСЛЕДОВАНИЕ
Хотя открытые члены базового класса при
наследовании с ключом доступа private в
производном классе становятся закрытыми,
внутри производного класса они остаются
доступными!

12.

НАСЛЕДОВАНИЕ
#include<iostream>
using namespace std;
class base{
int x;
public: void set_x( int n){ x=n;}
void show_x(){ cout< < x< <endl;
};

13.

НАСЛЕДОВАНИЕ
class derived : private base {
int y;
public: void set_xy( int n, int m){ set_x(n); y=m;}
void show_xy()
{ show_x() ; cout< < y< <endl ; }
};

14.

НАСЛЕДОВАНИЕ
int main() {
derived ob;
ob.set_xy(10,20);
ob.show_xy();
return 0;
}

15.

НАСЛЕДОВАНИЕ
#include<iostream>
using namespace std;
class samp{
int a;
protected : int b;
public : int c;
public: samp(int n, int m){ a=n; b=m;}
int get_a(){ return a; }

16.

НАСЛЕДОВАНИЕ
int main() {
samp ob(10,20);
// ob.b=99;
ob.c=30;
cout < < ob.get_a();
cout < < ob.get_b() < < ob.c;
return 0;
}

17.

НАСЛЕДОВАНИЕ
#include<iostream>
using namespace std;
class base{
protected int a,b;
public: void set_ab( int n, int m){ a=n; b=m; }
};

18.

НАСЛЕДОВАНИЕ
class derived : public base {
int c;
public: void set_c( int n){ c=n;}
void show_abc()
{ cout< < a< < b < < c < <endl ; }
};

19.

НАСЛЕДОВАНИЕ
int main() {
derived ob;
ob.set_ab(1,2);
ob.set_c(3);
ob.show_abc();
return 0;
}

20.

ПРИМЕР 4
#include<iostream>
using namespace std;
class base{
protected: int a,b;
public: void set_ab( int n, int m){ a=n; b=m; }
};

21.

ПРИМЕР 4
class derived : protected base {
int c;
public: void set_c( int n){ c=n;}
};
void show_abc()
{ cout< < a< < b < < c < <endl ; }

22.

ПРИМЕР 4
int main() {
derived ob;
ob.set_ab(1,2);
ob.set_c(3);
ob.show_abc();
return 0;
} // почему не будет работать?

23.

Конструкторы, деструкторы
Конструкторы выполняются в порядке
наследования.
Деструкторы выполняются в обратном порядке.
конструктор_производного_класса (список
аргументов) : базовый класс( список аргументов)
{
//тело конструктора производного класса
}

24.

#include<iostream>
using namespace std;
class base{
public: base(){ cout< < «base constructor»};
~base(){ cout < < «base destructor»; }
};

25.

class derived : public base {
int j;
public: derived( int n){ cout < < «derived
constructor»; j=n; }
~derived()
{ cout< <»derived destructor» < <endl
;}

26.

int main() {
derived ob(10);
ob.show_j();
return 0;
}

27.

#include<iostream>
using namespace std;
class base{
int i;
public:
base(int n){ cout< < «base constructor»; i=n; }
~base(){ cout < < «base destructor»; }

28.

class derived : public base {
int j;
public: derived( int n): base(n){ cout < <
«derived constructor»; j=n; }
~derived()
{ cout< <»derived destructor» <
<endl ; }
vcid show_j(){ cout < < j; }

29.

int main() {
derived ob(10);
ob.show_i();
ob.show_j();
return 0;
}

30.

#include<iostream>
using namespace std;
class base{
int i;
public: base(int n){ cout< < «base
constructor»; i=n; }
~base(){ cout < < «base destructor»; }

31.

class derived : public base {
int j;
public: derived( int n, int m): base(m){ cout < <
«derived constructor»; j=n; }
~derived()
{ cout< <»derived destructor» < <endl
;}

32.

int main() {
derived ob(10,20);
ob.show_i();
ob.show_j();
return 0;
}

33.

#include<iostream>
using namespace std;
class base{
int i;
public: base(int n){ i=n; }
void show_i(){ cout < < i;}
};

34.

class derived : public base {
int j;
public: derived( int n): base(n){ j=0; }
};
vcid show_j(){ cout < < j; }

35.

int main() {
derived ob(10);
ob.show_i();
ob.show_j();
return 0;
}

36.

Создать конструкторы car(), truck() . Они должны
передавать необходимые аргументы объектам
класса vehicle() . Конструктор car() должен при
создании объекта инициализировать переменную
passengers, а конструктор truck() -- переменную
loadlimit

37.

#include<iostream>
using namespace std;
class vehicle{
int num_wheels; int range;
public: vehicle(int w,int r){num_wheels=w;
range=r; }
void show_v(){ cout < < «число колес»

38.

class car : public vehicle{
int passenger;
public: // constructor car()
void show(){ show_v();
cout< < «число пассажиров»< < passengers;
}
};

39.

class truck : public vehicle {
int loadlimit;
public: // constructor truck()
void show(){ show_v();
cout< < «пробег»< < loadlimit; }
};

40.

int main() {
car c(5,4,500);
truck t(30000, 12, 1200);
cout < < «car »< < c.show();
cout< <»truck »< < t.show();
return 0;
}

41.

Создадим производный от класса monstr класс
daemon
enum color{ red, green, blue};
class monstr {
int health, ammo;
color skin;
char *name;

42.

public:
monstr( int he=100, int am=10);
monstr( color skin);
monstr (char *name);
monstr (monstr &M);
~monstr() {delete [ ] name; }

43.

monstr &operator ++() {++health; return * this;}
monstr &operator ++(int){ monstr M(*this); health++;
return M;}
operator int() {return health; }
bool operator > (monstr &M) {
if( health>M.health) return true;
return false;

44.

const monstr &operator =( monstr &M) {
if( &M= = this) return *this;
if(name) delete [ ] name;
if ( M.name) { name= new char[ strlen(M.name)+1];}
strcpy(name, M.name);
else name=0;
health=M.health; ammo=M.ammo; skin=M.skin; return
*this; }

45.

int get_health() const { return health;}
int get_ammo() const{ return ammo;}
void change_health(int he){health=he;}
void draw (int x, int y, int scale, int position);
};

46.

monstr :: monstr (int he, int am) : health(he),
ammo(am), skin(red), name(0){}
monstr:: monstr(monstr &M)
{ if(M.name) { name=new char[strlen(M.name)+1];
strcpy(name, M.name);}
else name=0;
health=M.health; ammo=M.ammo; skin=M.skin; }

47.

monstr :: monstr( color sk){
switch (sk)
case red : health=0; ammo=10; skin =red; name=0;
break;
case green : health=100; ammo=20; skin =green;
name=0; break;
case blue : health=100; ammo=40; skin =blue;
name=0; break; }
}

48.

monstr:: monstr( char *nam)
{
name=new char[ strlen(nam)+1];
strcpy( name, nam);
health=100; ammo=10; skin=red;
}

49.

void monstr :: draw (int x, int y, int scale, int position)
{
//отрисовка monstr
}

50.

class daemon : public monstr {
int brain;
public : daemon( int br=10){ brain=br;}
daemon( color sk): monstr(sk){ brain=10;}
daemon( char *nam):
monstr(nam){brain=10;}
daemon( daemon &M):monstr(M) {
brain=M.brain;}

51.

const daemon &operator =( daemon &M)
{
if( &M= =this) return *this;
brain=M.brain;
monstr:: operator =(M);
return *this; }
void think();
void draw(int x,int y, int scale, int position);

52.

void daemon:: think()
{
//… }
void daemon:: draw(int x, int y, int scale, int position)
{
//… }

53.

В классе daemon введено поле brain и метод think
;
Определены собственные конструкторы и оператор
присваивания , а также переопределен метод
draw()
Все поля класса monstr , операции ( кроме = ) и
методы get_health, get_ammo, change_health
наследуются в классе daemon ;
Деструктор формируется по умолчанию.

54.

Правила наследования
Конструкторы не наследуются, поэтому производный класс
должен иметь собственные конструктор.
Если в конструкторе производного класса явный вызов
конструктора базового класса отсутствует, автоматически
вызывается конструктор базового класса по умолчанию.
Для иерархии из нескольких уровней конструкторы базовых
классов вызываются , начиная с самого верхнего уровня.
В случае нескольких базовых классов конструкторы
вызываются в порядке объявления.

55.

Правила наследования
Если конструктор базового класса требует
указания параметров, он должен быть явным
образом вызван в конструкторе базового класса в
списке инициализации
Не наследуется операция =, ее также требуется
явно определить в производном классе

56.

Правила наследования
В записи оператора = в его теле применен явный
вызов оператора = из базового класса.
Ключевое слово operator знак-операции можно
интерпретировать как имя оператора
monstr:: operator=(M);

57.

Правила наследования
Вызов функции базового класса
предпочтительнее копирования фрагментов
программы из функций базового класса в функции
производного.

58.

Наследование
деструкторов
Деструкторы не наследуются.
Если программист не описал в производном классе
деструктор, он формируется по умолчанию и
вызывает деструкторы всех базовых классов.

59.

Наследование
деструкторов
При написании деструктора производного класса
в нем не требуется явно вызывать деструкторы
базовых классов, поскольку это будет сделано
автоматически.
Для иерархии, состоящей из нескольких уровней,
деструкторы вызываются в обратном порядке:
сначала деструктор производного класса, потом
деструкторы элементов класса, затем —
деструкторы базового класса.

60.

Наследование
деструкторов
Поля, унаследованные от monstr, недоступны функциям
производного класса, поскольку они объявлены как private
Если функциям, определенным в классе daemon требуется
работать с этими полями, можно или описать их в базовом
классе как protected, или обращаться к ним с помощью
функций из monstr, или явно переопределить их в daemon как
в примере.
В классе daemon метод draw() переопределяет метод draw()
класса monstr

61.

Наследование
деструкторов
Доступ к методу базового класса выполняется
через
monstr::
для производного класса!

62.

ЗАДАНИЕ
Выполнить программы из лекции — прислать скрин
экрана.
Прокомментировать последний пример на стр. 41-52
Срок выполнения — воскресенье 18.05 24:00
English     Русский Правила