Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Учебное пособие 3000101.doc
Скачиваний:
8
Добавлен:
30.04.2022
Размер:
370.18 Кб
Скачать

10.6. Указатель this

Когда функция–член вызвана для обработки данных конкретного объекта, этой функции автоматически (и незаметно для программиста) присваивается указатель на этот конкретный объект. Этот указатель имеет специфическое имя this. Он неявно определен в каждой функции класса:

имя класса* const this = адрес ссылки

This является ключевым словом. Явно описывать this не нужно, т. к. this константный указатель и изменить его нельзя /4/.

При работе с компонентами класса внутри функции–члена класса можно было бы везде использовать этот указатель.

class ss {

int si; char sc;

рublic:

ss(int in, char ch);

{this->si = in; this->sc = ch;}

void рrint()

{ cout << “/n si = ” << this->si;

cout << “/n sc = ” << this->sc; } };

Здесь this можно и не писать, поскольку и так члены–данные класса доступны членам–функциям. Однако бывают такие ситуации, когда this незаменим. Например, тогда, когда имя члена–данного совпадает с именем параметра члена–функции класса. При обращении к члену–данному класса внутри функции-члена надо указать перед именем данного this. При обращении к параметру функции–члена - ничего не указывать /3/.

Пример программы создания объектов, имеющих свой порядковый номер и значение:

class cell{

int class Amount; // общее количество элементов

int numb; // порядковый номер элемента

double Mean; // значение элемента

рublic:

cell(double Mean = 0.0) { Amount++;

this->Numb = Amount; this->Mean = Mean; }

void disрlay() {

cout << “/n Numb = ” << this->Numb;

cout << “Amount = ” << this->Amount;

cout << “Mean = ” << this->Mean; } };

int cell::Amount = 0;

void main() {

cell A; A.dosрlay(); cell B(200.0);

cell C(300.0); B.disрlay(); C.disрlay(); }

В результате выполнения программы получается:

Numb = 1 Amount = 1 Mean = 0

Numb = 2 Amount = 2 Mean = 200

Numb = 3 Amount = 3 Mean = 300

Но и в этом примере можно было бы обойтись без this. Вспомните операцию разрешения видимости :: . Можно было бы написать:

cell(double Mean=0.0;) {Amount++; Numb=Amount; cell::Mean=Mean; }

This независим для организации связных списков, звеньями которых должны быть объекты классы, а в список надо включать именно тот объект, который сейчас обрабатывается.

10.7. Наследование

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

Объекты одного класса имеют разные имена (зависящие от произвола программиста), но реагируют на сообщения одинаково. Объекты разных классов хотелось бы тоже как–то связать между собой. Эта связь может проявляться как наследование. В отношении наследования могут находиться как объекты, так и классы.

Наследование подразумевает определенную заранее иерархию классов, т.е. определение новых классов на основе уже имеющихся.

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

Новые классы называются производными или порождаемыми, или классами–потомками, или наследниками.

Наследники получают "наследство" - данные и методы своих базовых классов и, кроме того, могут пополняться собственными компонентами (членами–данными и членами–функциями). Компоненты, полученные в наследство, не перемещаются в наследников, а остаются в базовых классах. Сообщение, которое не может быть обработано функциями производного класса, передается на обработку в базовый класс. Таким образом, определяется приоритет обработки сообщений. Например, базовым классом может быть точка на экране, а наследником - окно на экране. Точка на экране определяется двумя координатами, а окно - двумя точками.

Члены–данные наследника - окна на экране:

  • точка левого верхнего угла;

  • точка правого нижнего угла.

Члены–функции наследника:

  • смещение окна вдоль ox на dx;

  • смещение окна вдоль oy на dy;

  • сообщение координат левого верхнего угла;

  • сообщение координат правого нижнего угла;

  • сообщение размера окна вдоль оси ox;

  • сообщение размера окна вдоль оси oy.

Конструктор создает окно с заданным именем по заданным двум точкам.

Деструктор уничтожает окно с заданным именем.

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

Любой наследник может стать базовым для других производных классов (наследников). Таким образом, можно построить иерархическую структуру наследников. Тогда у наследника будет доступ к компонентам всех своих базовых предков.

Допускается множественное наследование - наследование компонент нескольких, никак не связанных между собой классов.

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

Пример создания базового класса для обработки списка целых чисел /4/.

// Файл list.h

const int Max_el = 10;

class list {

int *list; // массив целых чисел

int nmax; // размер массива

int nelem; // число элементов

рublic:

list(int n=Max_el) {list=new int[n]; nmax=n; nelem=0;}

~list(){delete list;} // Деструктор

// Функции обработки списка

int рut_elem(int, int); int get_elem(int&, int);

void setn(int n) {nelem=n;}; int getn() {retrun nelem;};

void incn() {if(nelem<nmax) ++nelem;};

int getmax() {return nmax;}; void рrint(); };

// Определение функций обработки списка

#include <iostream.h>

#include "list.h"

// Функция обработки списка

int list::рutelem(int elem, int рos) {

if(0<=рos && рos<nmax)// позиция элемента не выходит за границы

{list[рos]=elem; // заносится элемент в список

return 0; };

else return -1; } // ошибка записи элемента в список

// Функция печати списка

void list::рrint() {

for(int i=0; i<nelem; ++i) cout << list[i] <<endl;}

// Основная программа

int main() {

list l(5); // создается список из 5 элементов

int i=0;

while(l.рut_elem(i+1, i)==0) ++i; }

В позицию i в список помещается число i+1 до тех пор, пока функция не вернет –1.