Программирование >>  Структура ядра и системные вызовы 

1 ... 4 5 6 [ 7 ] 8 9 10 ... 98


последнем производном классе. Например, в приведенном выше примере класс Base считается открытым базовым классом в классе С.

Ниже демонстрируется последовательность вызовов функций-конструкторов и функций-деструкторов виртуальных и невиртуальных базовых классов, а также вызов функции виртуального базового класса {baser.prinf) в объекте последнего производного класса:

source module: virtual base.C

♦include <stream.h> : ,

class base { public: int x;

base(int xa=0) : x(xa} ( cerr base( xa )

. .- ),5called\n .; ); virtual void printO cerr x= x \n ; };

virtual ~base() ( cerr ~base() calledXn ;)

class dl : virtual public Ьавгвдг ( ,

public:

int y;

dl{int xa, int ya) : base(xa)

cerr dl( xa , ya ) called ; у = ya;

~dl() { cerr ~dH) calledXn ; );

void print{) ( cerr y= у \n ; };

class d2 : virtual public base

public: int z;

d2(int xa, int za) : base(xa) (

.cerr d2( xa ; ,. za ) called\n ; z = za;

~d2() { cerr ~d2() calledXn ; );

c:(.ass derived : public dl, public d2

public: int all;

derived(int a, int b, int c, int d) : base(a), dl(a,b), d2(a,c), all(d)

{ cerr derived( all ) calledXn ;);

void prints 0 { base::print(); cerr ;all= all Xn ;};

int main 0 {

derived food, 2, 3,4) ? foo.prints 0; return 0;

Компиляция и пробный запуск этой программы дают следующие результаты:

% СС virtual base.C % а.out base(l) called did, 2) called d2(l,3) called derived(4) called x=l all=4

~d2() called ~dl() called -baseO called

2.8. Абстрактные классы

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

В абстрактном классе объявляется одна или несколько чистых (pure) виртуальных функций; эти функции не имеют определений, и все подклассы этого абстрактного класса должны их переопределять. Чистая виртуальная функция объявляется следующим образом:

class abstract base {

public:

virtual void draw() =0; чистая виртуальная функция

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

Проиллюстрируем использование абстрактного класса на примере интерактивной программы, вьщающей пользователю меню, в котором он должен выбирать необходимые операции. Каждая операция инкапсулируется одним объектом типа menu obj. Класс menuobj произведен от класса аЬ-stract base. Последний представляет собой абстрактный базовый класс и содержит две чистых виртуальных функции: info и орг, которые переопределяются в классе menuobj. Функция info вызывается для демонстрации одного



из способов использования объекта класса menujobj, а функция орг - для выполнения реальной операции с объектом типа menuobj.

В этом примере определены три объекта класса menujobj: один - для вывода на экран значения местного времени и даты, второй - для вывода значения времени и даты по Гринвичу, а третий - для завершения программы. Эти объекты хранятся в диспетчерской таблице, которая называется menu. Функция main организовывает циклическое выполнение функции menujobj.-.info для всех объектов, которые хранятся в menu, с целью вывода меню на консоль. Затем она принимает от пользователя входные данные (выбор элемента меню) и вызывает функцию menujobjг.орг соответствующего объекта. Отметим, что данная программа предусматривает возможность модернизации. Пользователи могут определять новые объекты класса menujobj и записывать их в menu, а программа будет автоматически вводить эти объекты в действие:

source module: abstract.С ♦include <iostream.h> ♦include <stdlib.h> ♦include <time.h>

♦include <string.h> , ч!

typedef void (*PF)();

class abstragt base

абстрактный базовый класс для отображения информации

protected:

PF fn ptr;

char *info msg ; public:

abstract base(PF fn=0, char* msg=0) (fn j)tr=fn, info msg=msg; ); virtual void info(int) =0; virtual void opr() =0;

class menu obj : public abstract base производный класс (

public:

menu obj(PF fn, char *msg) : abstract base(fn,msg) (); void info(int menu idx)

- :k : - . j :,V :

cout mehu idx << . ic< info m3g <<Ф\п ;

void opr() ( this->fn ptr0; );

}; , , .

inline void fnO() (

long tim = time(O);

cerr Local: asctime (localtime (&tim) ) \n ;

) ,

inline void fnl() {

long tim = time(O);

cerr GMT: asctime(gmtime(Stim) ) \n ;

inline void fn2() { ex:it(0); )

dispatch table menu obj menu[] = (

menu obj(fnO, Local data:time ), menu obj(fnl, GMT date:time ), menu obj(fn2, Exit program )

♦define MENU SIZ sizeof(menu)/sizeof(menu[0])

inline void display menu() (

for (int i=0; i<MENU SIZ; i++) menu[i].info (i);

int main() (

for (int idx; 1; ) display nienu O*;

cout Select (0- (MENU SIZ-1) )> ; cin idxi

if (idx >=0 && idx<MENU SIZ)

menu(idx].opr(); else cerr Illegal input: idx \n ;

return 0; )

Компиляция и пробное выполнение этой программы дают следующие результаты;

% СС abstract.с % a.out

0: Local date:time 1: GMT date:time 2: Exit Program Select (0-2) : 0

Local: Sun Apr 13 19:38:21 1997

0: Local date:time

1: GMT date:time

2: Exit Program

Select (0-2): 1

GMT: Sat Apr 12 02:38:22 1997

0: Local date:time ,

1: GMT date:time 2: Exit Program Select (0-2) : 2



2.9. Операции new и delete

в С++ определены операции new и delete, предназначенные для динамического управления памятью, Считается, что их применение с этой целью более эффективно, чем использование С-функций malloc, calloc и free.

Аргументами операции new являются тип данных (или класс) и, при необходимости, заключенный в круглые скобки список данных инициализации для функции-конструктора нового объекта. Если данные инициализации не указаны, то либо вызывается функция-конструктор нового объекта, которая не принимает аргументов (если она определена), либо новый объект не инициализируется.

Пусть, например, есть такое объявление класса:

class date {

int year, moflth, day; public:

date( int a, int b, int с ) { year=a, month=b, day=c; ); dateO {year = month = day =0; }; -dateO {};

В представленных ниже двух операторах используются два разных конструктора класса date:

date *datelp = new date (1997,7,1); используется date:: date (int, int, int); date *date2p = new date; используется date::date();

С помощью операции new можно выделить массив объектов. Для этого нужно указать имя класса и (в квадратных скобках) число объектов в массиве. Так, следующий оператор выделяет массив из десяти объектов, тип которых задает класс date:

date *dateList = new date [ 10 ];

Чтобы инициализировать объекты массива, выделяемые операцией new, класс этого объекта должен иметь конструктор, не требующий аргументов и используемый для инициализации каждого объекта в массиве. Если такой конструктор не определен, объекты массива не инициализируются.

В стандартной библиотеке С++ определена глобальная переменная new handler. Если она является указателем на заданную пользователем функцию, то каждый раз, когда операция new не может бьггь выполнена, вызывается эта подпрограмма, выполняющая определяемые пользователем действия по устранению ошибки. Затем подпрограмма возвращает вызвавшей ее программе значение указателя NULL. Если newjtandle установлена в свое стандартное значение NULL, то при сбое операция new просто возвращает вызвавшей ее программе значение указателя NULL.

Переменная new handler объявляется в заголовке <new.h> следующим образом:

extern void (* new handler) ();

Этой переменной можно задавать значение либо прямым присваиванием в пользовательских программах, либо с помощью макрокоманды setnew Jiandler из <new.h>:

♦include <new.h>

extern void error handler(); определяемая пользователем функция main О . ,! ; . . ..

new handler = error handler; , прямое присваивание set new handler ( error handler ); 7/ присваивание через макрос

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

♦ include <new.h>. ♦include date.h

const NUM OBJ = 1000;

date *pool = hew char[size(DATE)*NUbOBJ];

int main()

date *p = new (pool) date [NUM OBJ]; delete [NUM OBJ] p;

В этом примере пользователь выделяет область памяти, на которую указывает переменная pool, а затем выделяет память под NUM OBJ объектов класса date. Массив данных размещается в области памяти, начинающейся с адресаи на него указывает переменная р. С помощью операции delete он освобождается.

Динамический объект, выделенный операцией new, всегда освобождается операцией delete. Например, чтобы удалить объект класса date, на адрес которого указывает переменная р, нужно сделать следующее:

date *р = new date; delete р;

Если подлежащий удалению объект - это массив, то после ключевого слова delete необходимо указать число элементов массива, а затем его имя. Например:

date *arrayP = new date[10j; delete [10] array?;



1 ... 4 5 6 [ 7 ] 8 9 10 ... 98

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика