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;

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


 

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

83469. Доктрини визнання урядів 35.14 KB
  Історії міжнародного права відомі спеціальні доктрини про визнання урядів, названі іменами міністрів закордонних справ Еквадору Карлоса Тобара (доктрина Тобара) і Мексики Хенаро Естради (доктрина Естради), що сформувалися на початку XX століття в практиці держав американського континенту.
83471. Інститут правонаступництва держав в міжнародному праві. Джерела міжнародного правонаступництва 35.98 KB
  Джерела міжнародного правонаступництва Для стабільності міжнародних відносин важливе значення має послідовне виконання суб’єктами міжнародного права укладених ними міжнародних договорів їх міжнародних зобов’язань щодо території власності членства у міжнародних організаціях тощо. Інститут правонаступництва у міжнародному праві є міжгалузевим інститутом: його норми містяться в праві міжнародних договорів праві міжнародних організацій міжнародному економічному праві та ін. Тривалий час основу інституту правонаступництва складали звичаєві...
83472. Поняття правонаступництва в міжнародному праві. Види і форми правонаступництва. Підстави правонаступництва 37.07 KB
  Види і форми правонаступництва. Підстави правонаступництва. Таким чином правонаступництво являє собою правовідносини у яких беруть участь дві сторони: державапопередниця яка була змінена іншою державою в процесі правонаступництва; державаспадкоємниця яка замінила іншу державу в процесі правонаступництва.
83473. Міжнародне правонаступництво держав щодо міжнародних договорів 38.6 KB
  Відносно усних договорів і договорів між державами й іншими суб’єктами міжнародного права діють звичаєві норми міжнародного права. встановлює наступні правила правонаступництва щодо міжнародних договорів: а у разі створення в результаті деколонізації нової незалежної держави діє принцип tbul rs чистої дошки: нова держава не зв’язана договорами укладеними колишніми державамиметрополіями і не зобов’язана зберігати чинність будьякого договору або ставати його учасницею в силу виключно того факту...
83474. Міжнародно-правове регулювання правонаступництва держав відносно міжнародних договорів, державної власності, державних архівів та боргів 37.84 KB
  Однією з найважливіших проблем правонаступництва щодо державної власності є проблема компенсації за власність що переходить до державинаступниці. передбачається що в принципі такий перехід власності повинен відбуватися без компенсації якщо інше не узгоджено зацікавленими державам або не передано на вирішення відповідного міжнародного органу Державапопередниця зобов’язана вжити всі заходи для запобігання пошкодження або знищення власності що переходить до державинаступниці. Правонаступництво не стосується власності яка знаходиться на...
83475. Правонаступництво України в зв’язку з розпадом СРСР 39.9 KB
  Правонаступництво України щодо Союзу PCP регулюється комплексом домовленостей з питань правонаступництва що були досягнуті між країнами які увійшли після розпаду СРСР у Співдружність Незалежних Держав серед них: Меморандум про взаємопорозуміння з питань правонаступництва щодо договорів колишнього Союзу PCP що становлять взаємний інтерес 1992 p. Україна є правонаступницею прав і обов’язків СРСР які не суперечать Конституції України. було закріплено що кожна держава СНД має право підтвердити чинність для себе міжнародних договорів СРСР.
83476. Поняття і види територій в міжнародному праві 35.51 KB
  За правовим режимом територія поділяється на три основні види: 1 державна територія; 2 міжнародна територія; 3 територія із змішаним режимом. Державна територія це частина простору земної кулі що знаходиться під суверенітетом держави яка здійснює відносно неї і в її межах своє територіальне верховенство. Територія із змішаним режимом територія на якій одночасно діють норми міжнародного та національного права. До територій зі змішаним режимом також відноситься державна територія міжнародного користування що включає міжнародні річки...
83477. Демілітаризовані і нейтралізовані території 36.41 KB
  Демілітаризована територія - це територія, відносно якої держава прийняли міжнародне зобовязання скоротити або взагалі не розташовувати в її межах військові укріплення і споруди, певні види озброєнь збройних сил. Такі території створюються на основі міжнародних угод з метою забезпечення міжнародної безпеки.