Скачиваний:
3
Добавлен:
20.05.2014
Размер:
411.65 Кб
Скачать

15.5 Пример класса Tkplk

#include <iostream.h >

#include <conio.h >

#include <string.h >

class Tkplk {

private: int sum;

public: int hei, wei, cvet;

char nazv[20];

void show (int kodrm) ;

void add (int kop);

Tkplk ( int , int , int ,char * ); //это прототип конструктора

//- - - - - - - - - - - - - - - -

int dzin() { // разбиваем копилку

cout<< " Broken with sum= "<<sum<<endl; return 1; }

}; // end of class - - - - - - - - - - - - - - - -

void Tkplk::show ( int kodrm) {

cout << "ris. kopilki with hei="

<< hei<<" wei= "<<wei<<" cvet="<<cvet<<endl;

cout<< " It is ";

for(int j=0; j<strlen(nazv);j++) cout<<nazv[j];

cout<<endl; if( kodrm==1) cout<< "ris. ramki"<<endl;

}

//- - - - - - - - - - - - - - - -

void Tkplk::add (int kop) {

sum +=kop; }

//- - - - - - - - - - - - - - - -

Tkplk::Tkplk ( int he=10, int we=10, int cv=10,char *nz="cat" )

{ sum=0; hei=he; wei=we;

cvet=cv;

for (int m=0; m<=strlen(nz); m++) nazv[m]=nz[m];

// <= for last symbol '\0'

}

// - - - - - - - - - - - - -

void main() {

Tkplk myKplk1, myKplk2(15,15,15,"tiger");

cout<< " myKplk1.hei="<<myKplk1.hei <<endl;

cout<< " myKplk2.hei="<<myKplk2.hei <<endl;

cout<< " strlen(myKplk2.nazv)="<<strlen (myKplk2.nazv);

cout<<endl;

myKplk1.show(1); myKplk2.show(0);

cout<<"end show"<<endl;

myKplk2.add(50); myKplk2.add(30);

myKplk1. dzin(); // cout<<myKplk1.sum;

myKplk2.dzin(); getch();

}

// - - - - - - - - - - --

15.6 Заключение к лекции 15

1. Класс содержит данные, методы и конструкторы, причем любая часть или любая пара

из этих трех частей может отсутствовать.

2. Обычно методы, т.е. принадлежащие классу функции, записываются вне

определения класса с указанием полного имени

тип_функц класс : : функц ( аргументы) { . . . текст функции . . . }

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

Это правило относится и к конструкторам класса.

3. Для работы с элементами класса должны быть созданы объект или объекты

этого класса. Обращение к элементу записывается с именем объекта или с указателем

на объект.

Лекция 16 Наследование и полиморфизм

Эти принципы ООП уже рассматривались кратко в разделе 14.3. Повторим их и рассмотрим примеры использования.

16.1 Наследование

В больших программах часто возникает необходимость создания нового класса, который лишь немногими данными или функциями отличается от уже разработанного класса. Можно поступить следующим образом: переписать весь текст класса, дав ему новое имя, и затем внести в него необходимые исправления и дополнения. Но если изменений немного, то такой путь нерационален, так как приходится повторять много одинаковых операторов, что существенно удлиняет программу и затрудняет понимание её логики.

Н а с л е д о в а н и е - это использование классов-родителей (предков) для создания

классов-потомков. Эти классы называют также базовым и производным.

Создав какой-либо класс, можно создавать его модифицированные версии,

которые наследуют данные и методы класса - предка. При этом повторно используемые данные и методы можно в производном классе не описывать, что сокращает объем программы.

В С++ каждый класс может иметь сколько угодно потомков и родителей.

Связи классов представляются в виде иерархической структуры - дерева, похожего на деревья родословных (см. рис. 14.3 лекции 14). Возможна здесь и другая терминология:

класс-родитель = базовый класс = надкласс = суперкласс;

класс-потомок = производный класс = подкласс = субкласс.

Далее будем использовать термины: базовый и производный классы.

Пример заголовка для производного класса:

class circle : public figure

{ . . . дополнительные операторы нового класса . . . } ;

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

Если его нет, то по умолчанию все унаследованные элементы получают доступ private .

Появление слов public или protected означает, что доступ изменён. Существуют сложные правила о результатах сочетания двух модификаторов: доступа к элементам в базовом классе и доступа в заголовке производного класса, но рассматривать их не будем (см. [Подбельский], c.341).

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

Ради компактности программы резко уменьшим количество данных в классах фигура, прямоугольник, круг по сравнению с реальными задачами: оставим только два значения ( x, y) , определяющие размер фигуры. Для размеров x, y всех фигур выберем тип double (двойная точность), который характерен в С++ для представления вещественных чисел внутри ЭВМ. Напомним, что каждое значение типа double требует для хранения 8 байтов в отличие от 4 байтов для float.

Количество методов в классах также будет мало. Каждая фигура будет «уметь» лишь устанавливать свои размеры ( функция setdim ) и показывать свою площадь при этих размерах ( функция area ).

Выберем имена для классов: figure, rectangle, circle.

Класс figure будет базовым, а два других класса производными от него в соответствии с рис. 13.2 лекции 13.

В добавление к модификаторам private, public из раздела 15.2 потребуется третий модификатор – protected ( означает защищенный), который разрешает доступ «наследникам» к собственным элементам базового класса, т.е. к private – данным.

Все методы базового класса объявим как общедоступные (public).

// d:\Proba\ lect16 _area.cpp **** 27.9.2003

#include <iostream.h>

#include <conio.h>

class figure {

protected: double x, y;

public: void setdim (double , double ) ;

virtual void area( ) { cout<< "Unknown area here!!!!!!\n"; }

};

void figure : : setdim (double i, double j=0) {

x = i; y = j; }

// **** new class - - - - - - - - - - - - - - - - - -

class rectangle : public figure {

public:

void area ( )

{ cout<<" Rectangle with x= "<< x << " y= "<<y;

cout<<" Its area= " << x * y << endl; }

};

// **** new class - - - - - - - - - - - - - - - - - -

class circle : public figure {

public:

void area ( ) {

cout<<" Circle with x= " << x ;

cout<<" Its area = " << 3.141593 * x * x <<endl; }

} ;

// - - - - - - - - - - - - - - - - - -

void main ( ) {

figure f, *p ;

rectangle r1; circle c1;

p=&f; p-> setdim(1, 2.); p -> area ( ) ;

p=&r1; p-> setdim(5, 6.); p -> area ( ) ;

p=&c1; p-> setdim(7, 8); p -> area ( ) ;

p=&c1; p-> setdim( 7 ); p -> area ( ) ;

r1.setdim (9, 9.); r1.area ( );

с1.setdim (1, 0.); c1.area ( );

getch( ); }

В производных классах для прямоугольника и круга нам не нужно повторно описывать данные и функцию setdim, но потребуется изменить функцию area. Функция area во всех классах будет разной из-за изменения алгоритма вычисления площади каждой фигуры. Это одно из проявлений полиморфизма ( см. ниже): одинаковые имена, но разные алгоритмы.

Используем новое слово - virtual - для функции базового класса.

Virtual =фактический. Оно показывает, что в производном классе эта функция может быть изменена без изменения ее заголовка. Классы rectangle и circle являются производными от класса figure, что и показано в их заголовке. Производный класс может использовать лишь общедоступные (public) и защищенные (protected) элементы базового класса.

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

Unknown area here!!!!!!

Rectangle with x=5 y=6 Its area = 30

Circle with x=7 Its area = 153.938

Circle with x=7 Its area = 153.938

Rectangle with x=9 y=9 Its area = 81

Circle with x=1 Its area = 3.14159

Соседние файлы в папке Шпора по информатике