Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ООП.doc
Скачиваний:
77
Добавлен:
07.03.2016
Размер:
1.78 Mб
Скачать

Void main()

{

B d(1, 2, 3, 4);

C c(1, 2, 3, 4, 5);

cout << c.GetMater(); // Результат - 5.

}

Породжуючи один клас від іншого, можна легко прийти до такої ситуації, коли в декількох класах використовуються змінні і функції з однаковими іменами.

Приклад.

class A

{

public:

int foo() { return 1;}

};

class B: public A

{

public:

int foo() { return 2;}

};

Void main()

{

A a;

B b;

cout<<a.foo()<<"\n";

cout<<b.foo()<<"\n";

}

Клас В має дві функції foo(). Одна успадкована від А, інша – власна. При пошуку потрібної функції компілятор перегляне дерево спадкування починаючи з дерева В та використовує "найближчу" до класу функцію.

У прикладі результат відповідно 1 та 2.

У даному випадку ім’я в базовому класі переоголошується в похідному класі. Це одне й те ж, що оголошення змінних у складових операторних блоках: кожний блок має свою версію змінних і внутрішні імена подавлюють зовнішні.

Але є і відмінності. У C++ можна примусити компілятора "бачити" за межами поточної області видимості Це робиться за допомогою оператора дозволу видимості. Загальна форма цього оператору така:

<ім’я класу> :: <ідентифікатор із класу>

Для того, щоб використовувати оператор дозволу видимості, модифікуємо клас В в такий спосіб:

class B: public A

{

public:

int foo() { return А::foo();}

};

Тепер виклик функції В::foo() приведе до виклику foo() класу А. Оператор дозволу видимості використовується не тільки усередині функції класу, але і при виклику функції:

Void main()

{

B b;

B * b1;

int x = b. A::foo();

int y = b1-> A::foo();

}

Використання дозволу видимості після оператора "."

сlass A

{

public:

int value;

};

class B: public A

{

public:

int count;

};

Void main()

{

B b;

int i = b.count;

int j = b.B::count; // зайво, але правильно

int k = b.value;

int l = b.A::value; // зайво, але правильно

}

3.2 Множинне спадкування

У природі живі істоти мають двох батьків, що забезпечує більшу розмаїтість нащадка, покращує адаптування і виживання.

Приклад використання двох батьків (рис. 3.2):

Рис.3.2 Спадкування нащадком двох класів-батьків

#include <iostream>

using namespace std;

#define M_PI 3.14159265358979323846

class A

{

int a;

public:

A(int x) {a = x;}

float pl1() {return (M_PI*a*a);}

};

class AA

{

int aa;

public:

AA(int x) {aa = x;}

float pl2() {return (M_PI*aa*aa);}

};

class B: public A, public AA

{

int bb;

public:

B(int, int, int);

float pl3() {return (M_PI*bb*bb);}

};

B::B(int a, int b, int c):A(a), AA(b)

{ bb = c;}

Void main()

{

B ob(1, 2, 3);

cout << ob.pl1()<<"\n"<<ob.pl2()<<"\n"<<ob.pl3();

}

Розглянемо приклад спадкування з класами, що з’являються двічі (рис. 3.3):

Рис. 3.3. Спадкування з класами, що з’являються двічі

сlass A

{

public:

int val;

};

class B: public A { };

class C: public A { };

class D: public B, C

{

public:

int value() {return val;}

};

Компілятор не розуміє на яку копію val посилатися, тому для усунення неоднозначності треба у функції D::value застосувати оператор дозволу видимості:

int value() {return C::val;}

Функція поза класом D також могла б одержати доступ до кожної змінної val, використовуючи оператор дозволу видимості: