7.2 Абстрактные классы

---------------------

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

быть "пустыми", поскольку никогда не будут вызваны для объекта

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


class base

{

public:

virtual print() =0;

virtual get() =0;

}


Естественно, что определять тела этих функций не требуется.


7.3 Множественное наследование и виртуальные функции

---------------------------------------------------

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

Существенным для реализации множественного наследования является

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

то есть имеют фиксированные смещения относительно начала объекта:


class d : public a,public b, public c { };


d D1;

pd = &D1; // #define db sizeof(a)

pa = pd; // #define dc sizeof(a)+sizeof(b)

pb = pd; // pb = (char*)pd + db

pc = pd; // pc = (char*)pd + dc


D1

pd -------------------->-d---------¬

pa --------------------->-a-------¬¦T T

¦¦ ¦¦¦ ¦ db = sizeof(a)

¦L---------¦¦ +

pb --------------------->-b-------¬¦¦ dc = sizeof(a) + sizeof(b)

¦L---------¦¦

pc --------------------->-c-------¬¦+

¦L---------¦

¦ ¦

L----------

Преобразование ссылки на объект производного класса к ссылке

на объект базового класса требует добавления к указателю текущего

объекта this соответствующего смещения (db,dc), обратное преобразование - вычитание этого же смещения. Такое действие выполняется

компилятором, когда в объекте производного класса наследуется

функция из второго и т.д. базового класса, например при определении в классе "b" функции "f()" и ее наследовании в классе "d" вызов D1.f() будет реализован следующим образом:


this = &D1; // Адрес объекта производного класса

this = (char*)this + db // Адрес объекта класса b в нем

b::f(this); // Вызов функции в классе b со своим

// объектом


Рассмотрим особенности механизма виртуальных функций при

множественном наследовании. Во-первых, на каждый базовый класс в

производном классе создается своя таблица виртуальных функций (в

нашем случае - для "a" в "d", для "b" в "d" и для "c" в "d").

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

ссылку на объект базового класса в ссылку на объект производного,

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


class a

{

public: virtual void f();

virtual void g();

};

class b

{

public: virtual void h();

virtual void t();

};

class c : public a, public b

{ // f(),t() наследуются

public: void g(); // g() переопределяется

void h(); // h() переопределяется

}


a A1;

b B1;

c C1;

pa = &A1;

pb = &B1;


pa->f(); // Вызов a::f()

pb->h(); // Вызов b::h()


pa = &C1;

pb = &C1;


pa->f(); // Вызов a::f()

pa->g(); // Вызов c::g()

pb->h(); // Вызов c::h()

pb->t(); // Вызов b::t()


Таблицы виртуальных функций для данного примера имеют вид:


A1

-a----¬ Таблица ВФ для "a"

¦ ------------>--------¬

+-----+ ¦a::f() ¦

L------ +-------+

¦a::g() ¦

L------- B1

-b----¬ Таблица ВФ для "b"

¦ ------------>--------¬

+-----+ ¦b::h() ¦

L------ +-------+

¦b::t() ¦

L------- C1

T --c-----¬ Таблица ВФ для "a" в "c"

¦ ¦--a---¬¦ --------¬

db ¦ ¦¦ ----------->¦a::f() ¦

¦ ¦L------¦ +-------+

+ ¦--b---¬¦ ¦c::g() ¦

¦¦ -------¬ L------- ¦L------¦ ¦ Таблица ВФ для "b" в "c"

¦ ¦ ¦

¦ ¦ L--->--------¬ "Заплата" для c::h()

L-------- ¦ xxx()----->--xxx()----------------¬

+-------+ ¦ this=(char*)this - db¦

¦b::t() ¦ ¦ goto c::h ¦

L-------- L----------------------

Другим вариантом решения проблемы является хранение необходимых смещений в самих таблицах виртуальных функций.


7.4. Виртуальные базовые классы

------------------------------

В процессе иерархического определения производных классов

может получиться, что в объект производного класса войдут

несколько объектов базового класса, например


class base {}

class a : public base {}

class b : public base {}

class c : a, b {}


В классе "c" присутствуют два объекта класса base. Для исключения такого дублирования объект базового класса должен быть

объявлен виртуальным


class a : virtual public base {}

class b : virtual public base {}

class c : public a, public b {}


a A1;

b B1;

c C1;


Объект обыкновенного базового класса располагается, как правило, в начале объекта производного класса и имеет фиксированное

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

класса на соответствующем месте размещается не объект базового

класса, а ссылка на него, которая устанавливается конструктором.

Для вышеприведенного примера имеем


A1 B1 C1

--a------¬ --b-----¬ --c---------------¬

¦ ------¬ ¦ ------¬ ¦ --a-------¬ ¦

+--------+ ¦ +-------+ ¦ ¦ ¦ -------¬ ¦

¦ ¦ ¦ ¦ ¦ ¦ ¦ +---------+ ¦ ¦

¦-base--¬---------¬0 integer

+--------+ +--------+.. real

+--------+ +--------+j --dat-------¬

base** ¦ -------------->-base-----¬¦

+--------+ ¦L----------¦

base* ¦ ¦

L----------- base

head Строка заголовка БД

--¬ S0

¦-------------->---------¬0 -string---¬

L-- ¦ ------------------>-base---¬¦

base** +--------+ ---------->L--------¦

¦ --------------¬ L--------- +--------+ ¦ ¦ D0

¦ --------- ¦ -dat------¬

+--------+ L--->-base---¬¦

base* ¦L--------¦

L---------//------------------------------------------------------// Меню классов объектов (типов столбцов)

string S0;

dat D0;

time T0;

integer I0;


base *TYPE[] = {

(base*) &S0;

(base*) &D0;

(base*) &T0;

(base*) &I0;

};

//-----------------------------------------------------// Создание структуры БД


#define MAXCOL 30

#define MAXREC 1000


table::table()

{

int i,j,n;

char ss[80];

names = new char*[MAXCOL]; // Таблица адресов имен столбцов

head = new base*[MAXCOL]; // Таблица ссылок на объекты

for (nc=0; nc


Информация о работе «Объективное программирование»
Раздел: Информатика, программирование
Количество знаков с пробелами: 61028
Количество таблиц: 0
Количество изображений: 0

Похожие работы

Скачать
14044
1
2

... обучающих программ Обучающие программы, построенные на бихевиористской основе, подразделяют на: а) линейные, разработанные Скиннером, б) разветвленные программы Н. Краудера. 1. Линейная система программированного обучения, первоначально разработанная американским психологом Б. Скиннером в начале 60-х гг. ХХ в. на основе бихевиористского направления в психологии. ·  Он выдвинул следующие ...

Скачать
93027
12
0

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

Скачать
109055
0
0

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

Скачать
165676
21
12

... отбора. ГЛАВА II. ЦЕЛЬ, ЗАДАЧИ, МЕТОДЫ И ОРГАНИЗАЦИЯ ИССЛЕДОВАНИЯ   2.1 Цель и задачи исследования Цель исследования - повышение эффективности физической подготовки вратарей учебно-тренировочных групп на соревновательном этапе. В процессе реализации поставленной цели решались следующие основные задачи: 1.     Изучить особенности возрастного развития двигательных способностей футболистов ...

0 комментариев


Наверх