69725

Віртуальні базові класи

Лекция

Информатика, кибернетика и программирование

Як вказано в коментарях, класи derivedl і derived2 є спадкоємцями класу base. Проте клас deribed3 є похідним від обох класів derived2 і derived1. (Таке наслідуванно називається діамантовим). Отже, в об’єкті класу derived3 містяться дві копії об’єкту класу base.

Украинкский

2014-10-09

42 KB

0 чел.

Тема 3: Віртуальні базові класи

При множинному наслідуванні може виникнути неоднозначність. Розглянемо, наприклад, наступну неправильну програму.

//  Ця програма містить  помилку і не  компілюється.

#include <iostream>

using namespace std;

class base   {

public:

int  i;

};

// Клас derivedl є спадкоємцем класу base.

class derivedl : public base {

public:

int j ;

};

// Клас derived2 є спадкоємцем класу base 

class derived2 : public base {

public:

int k;

};

/* Клас derived3 є спадкоємцем класів derivedl і derived2. Отже, в класі

derived3 існують дві копії класу base! */

class derived3 : public derivedl, public derived2 {

public:

int sum;

};

int main() {

derived3 ob;

ob.i = 10; ob.j = 20; ob.k = 30;

// Неоднозначність, яка змінна i мається

// Тут змінна i також визначена неоднозначно.

ob. sum = ob. i + ob. j + ob.k;

// Тут змінна i також визначена неоднозначно

cout << ob.i << " ";

cout « ob.j « " " « ob.k « " ";

cout << ob.sum;

return 0;

}

Як вказано в коментарях, класи derivedl і derived2 є спадкоємцями класу base. Проте клас deribed3 є похідним від обох класів derived2 і derived1. (Таке наслідуванно називається діамантовим). Отже, в об'єкті класу derived3 містяться дві копії об'єкту класу base. Таким чином, вираз

 ob.i  =  20;

у якому відбувається звернення до змінної i, стає неоднозначним, оскільки невідомо, з об'єкту якого класу слід узяти цю змінну: derivedl або derived2. Володіючи двома копіями об'єкту класу base, об'єкт класу ob містить два екземпляри змінної ob.i! Як видимий, цей оператор в принципі неоднозначний.

Цю програму можна виправити двома способами. По-перше, до змінній i можна застосувати оператора дозволу області видимості. Наприклад, наступна програма працює абсолютно правильно

//   У  цій програмі для  явного  вибору  змінної  i

//   застосовується  оператор дозволу  області видимості.

#include  <iostream>

using namespace  std;

class  base   {

public:

int   i ;

};

// Клас derivedl є спадкоємцем класу base

class derivedl : public base {

public:

int j ;

};

// Клас derived2 є спадкоємцем класу base 

class derived2 : public base {

public:

int k;

};

/* Клас derived3 є спадкоємцем класів derivedl і derived2 одночасно.

Отже, в кожному його об'єкті містяться дві копії об'єкту класу base! */

class derived3 : public derivedl, public derived2 {

public:

int sum;

};

int main() {

derived3 ob;

ob.derivedl::i = 10; // Неоднозначність усунена

// використовується змінна i з класу derivedl .

ob.j = 20; ob.k = 30;

// Неоднозначність усунена

ob.sum = ob.derivedl::i + ob.j + ob.k;

// Неоднозначність усунена

cout « ob.derivedl::i « " ";

cout « ob.j « " " « ob.k « " "; cout << ob.sum;

return 0;

}

Як видимий, оператор дозволу області видимості "::" дозволяє явно вибрати варіант похідного класу. Проте це рішення породжує нові проблеми. Що якщо насправді потрібна лише одна копія об'єкту класу base? Чи можна запобігти дублюванню об'єктів класу base в об'єкті класу derivad3? На обидва питання можна відповісти позитивно. Вирішення цих проблем засноване на застосуванні віртуальних базових класів (virtual base classes).

Якщо базовий клас має декілька спадкоємців, його дублюванню можна запобігти. Для цього в оголошенні похідного класу перед ім'ям базового класу слід поставити ключове слово virtual. Наприклад, попередню програму можна виправити таким чином.

class derivedl : virtual public base {

public:

int j ;

};

// Клас derivedl є спадкоємцем віртуального класу base.

class derived2 : virtual public base {

public:

int k;

};

/* Клас derived3 є спадкоємцем класів derivedl і derived2.

Цього разу його об'єкт містить лише одну копію об'єкту базового класу. */

class derived3 : public derivedl, public derived2 {

public:

int sum;

};

Як видимий, перед ім'ям базового класу в специфікації похідного класу стоїть ключове слово virtual. Тепер обидва класи derivedl і derived2 є спадкоємцями віртуального базового класу base, і будь-які їх спадкоємці міститимуть лише одну копію класу base. Отже, об'єкт класу derived3 містить копію об'єкту класу base, і вираз ob.i=10 стає абсолютно правильним і однозначним.

Слід мати на увазі, що, хоча класи derivedl і derived2 оголосили клас base віртуальним, його об'єкти будуть як і раніше частиною об'єктів будь-якого з цих типів. Наприклад, наступний фрагмент є абсолютно правильним.

//   Визначуваний об'єкт  класу derivedl 

derivedl myclass; myclass.i  =   88;

Відмінність між звичайним базовим класом і віртуальним виявляється, тільки коли об'єкт успадковує декілька об'єктів одного і того ж базового класу. Якщо використовується віртуальний базовий клас, то його об'єкт тільки один раз копіюється в кожен об'єкт похідного класу. Інакше виникає неоднозначність.


 

А также другие работы, которые могут Вас заинтересовать

36166. Защита от ошибок в формате CD 52 KB
  Из теории помехоустойчивого кодирования известно что для коррекции t ошибок код должен иметь не менее 2t проверочных символов граница Синглтона. Значит каждый из них может исправить не более двух ошибок. Известно также что максимальное число гарантированно обнаруживаемых ошибок равно числу проверочных символов кода.
36167. SSD (Solid State Drive). Преимущества и недостатки 20.06 KB
  SSD логически эмулирует обычный жёсткий диск HDD и теоретически везде может применяться вместо него. SSD использующие динамическую память DRAM а не флэшпамять часто называются RAMdrive и имеют ограниченное применение например в качестве выделенного диска для файла подкачки ОС. Сердцем SSD является микросхема контроллера которая в первую очередь определяет такие ключевые характеристики SSD как внешний интерфейс быстродействие и энергопотребление. Преимущества и недостатки Преимущества SSD над HDD.
36168. Магнитные головки для записи информации на жесткий диск 112 KB
  Вначале это были монолитные головки. Композитные головки выполнены из феррита на подложке из стекла или твердой керамики и имеют меньшие размеры в сравнении с монолитными. Дальнейшим развитием технологии композитных головок стали так называемые головки MIGтипа MIG Metal In Gap.
36169. Технологии записи на магнитные диски 206 KB
  Домены магнитных материалов используемых в продольной записи располагаются параллельно поверхности носителя. Этот эффект и используется при записи цифровых данных магнитным полем головки изменяющимся в соответствии с сигналом информации. Попытки увеличить поверхностную плотность записи путем уменьшения размеров частиц будут увеличивать отношение размера зоны неопределенности к размеру полезной зоны не в пользу последней и в конце концов неизбежно приведут к так называемому суперпарамагнитному эффекту когда частицы перейдут в однодоменное...
36170. ОПТИЧЕСКИЕ ГОЛОВКИ 260 KB
  Задача эта непростая поскольку большинство оптических элементов адаптировано как правило для работы с излучением только одной длины волны. Вопервых необходимо было обеспечить приемлемое рабочее расстояние объектива при любой длине волны излучения. Вовторых обеспечить компенсацию сферических аберраций также при любой длине волны излучения. Втретьих обеспечить изменение числовой апертуры объектива в зависимости от длины волны проходящего через него света.
36171. SuperAudioCD 87 KB
  Следует заметить что технология одноразрядного квантования используется сейчас и для преобразования звука в других форматах однако там полученный одноразрядный поток в конце концов всетаки приводится к последовательности многоразрядных отсчетов 16 20 24разрядных и в дальнейшем все операции по формированию потока данных перед записью на носитель производятся уже с ними. Этот слой является носителем данных DSD и считывается оптической головкой с числовой апертурой 06 лучом лазера с длиной волны излучения 650 нм. В процессе...
36172. Варианты формата CD 133 KB
  Такая версия компактдиска появилась в 1985 году и получила название CDROM Read Only Memory память только для чтения. Поскольку диск CDROM предстояло использовать в составе вычислительных комплексов различной сложности то для него был разработан специальный дисковод легко вписывающийся в архитектуру компьютера. Дополнительное кодирование в CDROM производится до того как данные поступают на кодер CIRC точно такой же как в системе защиты от ошибок формата CDAudio. В формате CDROM эти 24 символа являются обезличенными и могут нести...
36173. ИЗГОТОВЛЕНИЕ BD-ДИСКОВ 401 KB
  Мастеринг BDдисков Существует три основные технологии мастеринга BDдисков: метод PTM иммерсионный метод и метод записи пучком электронов. Системы EBR Electron Beam Recorder использующие для записи пучок электронов наиболее дороги но позволяют получить очень высокое разрешение.1 иллюстрирует процесс формирования дорожки записи. Такая длина волны близка к длине волны излучения газовых лазеров которые применяются для записи оптических дисков в форматах CD и DVD.
36174. Структура минидиска 56.5 KB
  Частота сигнала вобуляции равна 2205 кГц. Эту частоту легко получить путем деления пополам частоты дискретизации звукового сигнала fд = 441 кГц. Кодирование данных DIP производится перед изготовлением диска путем частотной модуляции несущей fн = 2205 кГц бифазным кодом. Модуляция осуществляется с помощью тактовой частоты fт = 6300 Гц которая получается путем деления частоты дискретизации 441 кГц на 7 см.