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;

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


 

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

73630. Риск-менеджмент в организации 144.78 KB
  Рискменеджмент в организации Система управления риском. Развитие концепции управления риском. Общая характеристика системы управления риском. Свойства системы управления риском.
73631. СВІТОВА ВАЛЮТНА СИСТЕМА 376 KB
  Ця мета потребує щоб: окремі країни проводили економічну та фінансову політику яка б сприяла підтриманню збалансованої міжнародної системи платежів; фінансові механізми забезпечували регулювання платіжного балансу; уряди сприяли збереженню рівноваги на ринках іноземної валюти. Основні елементи національної і світової валютних систем Національна валютна система Світова та міжнародна валютні системи Національна валюта Резервні валюти міжнародні рахункові валютні одиниці Умови конвертування національної валюти Умови взаємного конвертування...
73632. Міжнародна міграція робочої сили 206.5 KB
  Міжнародна міграція робочої сили. Регулювання міжнародної міграції робочої сили. Сутність структура та основні риси світового ринку праці Одним із важливих елементів глобальної економічної системи на яку перетворився світ наприкінці другого тисячоліття є міжнародний ринок праці з його уніфікованою шкалою критеріїв щодо якості трудових ресурсів розвитком нових форм зайнятості гнучкістю та надзвичайною мобільністю сукупної робочої сили. Світовий міжнародний ринок праці це система відносин що виникають між державами з приводу...
73633. Міжнародні розрахунки і платіжний баланс 121.5 KB
  Економічний зміст платіжного балансу та методологія складання. Економічний зміст платіжного балансу та методологія складання. Стан платіжного балансу визначає попит і пропозицію національної й іноземної валюти в цей момент і він є одним із факторів формування валютного курсу. Прибуткові та витратні статті балансу міжнародних рахунків Прибуткові статті Джерела грошових коштів Витратні статті Способи використання грошових коштів Експорт товарів та послуг Імпорт товарів та послуг Приток капіталу Вивіз капіталу Приватні та...
73634. Реформы А.Н. Косыгина и причины их неудач 73.1 KB
  Для изучения этой системы и хода реформы дают материал интервью взятые у министра легкой промышленности СССР 1965 1980 гг. начальника главного управления трикотажной и текстильногалантерейной промышленности Софьи Николаевны Чупрыгиной. Министерство легкой промышленности СССР являлось такой же частью системы государственного управления как другие министерства и принципы его работы были такими же как у них. он прошел путь от сменного мастера на Ореховозуевском хлопчатобумажном комбинате до министра легкой промышленности СССР.
73635. Ответственность организаций и исполнителей за нарушение метрологического обеспечения 75.5 KB
  Дисциплинарная и материальная ответственность исполнителей за нарушение законодательства о метрологическом обеспечении производства и испытаний продукции Федеральный закон Российской федерации О техническом регклировании постатейный коментарий...
73637. Співвідношення культури та цивілізації 1.5 MB
  Співвідношення культури та цивілізації Певні теоретичні міркування саме під таке розуміння цивілізованості підвів американський соціолог та культуролог Л. Морган намагався відрізняти давні перші цивілізації від сучасної цивілізації яка У базується на наукових знаннях та технічних досягненнях Упередбачає високий рівень культури релігійної свободи демократичних прав правового регулювання міжнародних відносин. Досить резонансною та багато в чому пророчою постала книга Освальда Шпенглера Занепад Європи в якій цивілізація...
73638. Статистика населения 160.5 KB
  Для полного и точного учета численности населения необходимо определить границы территории, на которой учитывается население, и установить время, к которому относятся данные о численности населения. Учет населения производится по населенным пунктам