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

Тема8.Производные классы (2 часа)

8.1. Определение производного класса

Вспомним определение наследования, тесно связанного с понятием производных классов.

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

Существующие классы называются базовыми, а новые –производными. Производный класс наследует описание базового класса; затем он может быть изменен добавлением новых членов, изменением существующих функций-членов и изменением прав доступа. Таким образом, наследование позволяет повторно использовать уже разработанный код, что повышает производительность программиста и уменьшает вероятность ошибок. С помощью наследования может быть создана иерархия классов, которые совместно используют код и интерфейсы.

При наследовании некоторые имена методов и данных базового класса могут быть по-новому определены в производном классе. В этом случае соответствующие компоненты базового класса становятся недоступными из производного класса. Для доступа к ним используется операция указания области видимости '::'.

В иерархии производный объект наследует разрешенные для наследования компоненты всех базовых объектов (public,protected).

Допускается множественное наследование – возможность для некоторого класса наследовать компоненты нескольких никак не связанных между собой базовых классов. В иерархии классов соглашенияотносительно доступности компонентов класса следующие:

private– Член класса может использоваться только функциями-членами данного класса и функциями-"друзьями" своего класса.В производном классе он недоступен.

protected – То же, что и private, но дополнительно член класса с данным атрибутом доступа может использоваться функциями-членами и функциями-"друзьями" классов, производных от данного. Ключевое слово protected (в переводе с английского - защищенный) введено для того, чтобы сохранить сокрытие данных для членов, которые должны быть доступны из производного класса, но в других случаях действуют как закрытые, т.е. private.

public– Член класса может использоваться любой функцией, которая является членом данного или производного класса, а также кpublic-членам возможен доступ извне через имя объекта.

Следует иметь в виду, что объявление friendне является атрибутом доступа и не наследуется.

Синтаксис определения производного класса:

class имя_класса : (public| protected| private) список_базовых_классов

{список_компонентов_класса};

8.2. Правила использования атрбутов доступа

Явно изменить умалчиваемый статус доступа при наследовании можно с помощью атрибутов доступа – private,protectedиpublic, которые указываются непосредственно перед именами базовых классов. Как изменяются при этом атрибуты доступа в производном классе показано в следующей таблице

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

атрибут в базовом классе

атрибут, полученный в производном классе

public

public protected private

public protected недоступен

protected

public protected private

protected protected недоступен

private

public protected private

private private недоступен

Таким образом, можно только сузить область доступа, но не расширить.

Итак, внутри производного класса существует четыре уровня, для которых определяется атрибут доступа:

  • для членов базового класса;

  • для членов производного класса;

  • для процесса наследования;

  • для изменения атрибутов при наследовании.

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

Доступ извне.

Доступными являются лишь элементы с атрибутом public.

Собственные члены класса.

Доступ регулируется только атрибутом доступа, указанным при описании класса.

Наследуемые члены класса.

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

Пример 8.1

class Basis

{

protected:

int b, c;

public:

int a;

};

class Derived : public Basis

{

public:

Basis::c;

};

int main (void)

{

Basis ob;

Derived od;

ob.a; // правильно

ob.b; // ошибка

od.c; // правильно

od.b; // ошибка

return 0;

}

Доступ изнутри.

Собственные члены класса.

private и protected члены класса могут быть использованы только функциями-членами данного класса.

Наследуемые члены класса.

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

protected или public члены класса доступны для всех функций-членов. Подразделение на public, protected и private относится при этом к описаниям, приведенным в базовом классе, независимо от формы наследования.

Пример 8.2

class Basis

{

public:

void f1(int i)

{

a = i;

b = i;

}

int b;

private:

int a;

};

class Derived : private Basis

{

public:

void f2(int i)

{

a = i; // ошибка

b = i; // правильно

}

};

Следующий пример познакомит нас более подробно с синтаксисом наследования в С++. В примере приведено описание базового класса (Base1), public-производного класса (PublicDerived1) и private-производного класса (PrivateDerived1). Для иллюстрации всех изменений в разграничении доступа эти классы имеют поля данных и функции-члены в каждой из закрытой, защищенной и открытой частях. Объекты (они же экземпляры класса) всех классов объявлены в функции main:

Пример 8.3

class Base1 //создание базового класса

{

private: //закрытые данные

int data1;

int function1();

protected: //защищенные данные

int data2;

int function2();

public: //открытые данные

int data3;

int function3();

};

class PublicDerived1:public Base1 //создание public-производного класса

{

private: //закрытые данные

int data4;

int function4();

protected: //защищенные данные

int data5;

int function5();

public: //открытые данные

int data6;

int function6();

};

class PrivateDerived1:private Base1 //создание private-производного класса

{

private: //закрытые данные

int data7;

int function7();

protected: //защищенные данные

int data8;

int function8();

public: //открытые данные

int data9;

int function9();

};

void main()

{

Base1 aBase1; //экземпляр базового класса

PublicDerived1 aPublicDerived1; //экземпляр public-производного класса

PrivateDerived1 aPrivateDerived1; //экземпляр private-производного класса

}

Разберем правила доступа к закрытым, защищенным и открытым частям классов Base1, PublicDerived1 и PrivateDerived1. Т.е. выясним, что к чему имеет доступ...

Доступ к протоколу класса. Обращаем Ваше внимание на то, что описание класса имеет доступ ко всем своим собственным частям. Вполне естественно, что любая функция-член в закрытой, защищенной или открытой частях описания класса имеет прямой доступ ко всем полям данных и всем функциям-членам описания своего класса. Таким образом, любая функция-член в классе Base1 имеет прямой доступ к data1, data2, data3, function1, function2 и function3. Аналогично, любая функция-член класса PublicDerived1 имеет прямой доступ к data4, data5, data6, function4, function5 и function6. Любая функция-член в классе Private-Derived имеет прямой доступ к data7, data8, data9, function7, function8, function8.

Доступ через протокол производного класса. Производные классы наследуют все протоколы (включая все поля данных и функции-члены) от своего базового класса. Однако, производный класс не имеет прямого доступа к полям данных или функциям-членам, определенным в закрытой части его базового класса. Классы PublicDerived1 и PrivateDerived1 наследуют data1 и function1 от своего базового класса (Base1), но не имеют прямого доступа к ним. Доступ можно обеспечить через функцию, определенную в защищенной или открытой частях класса Base1. Эта функция будет наследоваться открытыми и защищенными производными классами и будет доступна им.

Доступ через объекты класса. Объекты класса не имеют доступа к закрытой и защищенной частям описания класса. Они не могут получить прямой доступ к полям данных в закрытой и защищенной частях. Таким образом, объект aBase1 не имеет доступ к своим собственным закрытым элементам data1 и function1. Аналогично, объект aBase1 не имеет доступа к своим собственным защищенным элементам data2 и function2.

Доступ через объекты public-производного класса. Объекты public-производного класса не имеют доступа к закрытой и защищенной части базового класса. Если в классе Base1 определены открытые функции для доступа к закрытым или защищенным полям через объекты классов, то эти функции наследуются public-производными классами и могут использоваться объектами этих классов. Объекту aPublicDerived1 недоступны его собственные закрытые элементы data4 и function4.

Доступ через объекты private-производного класса. Объекты private-производного класса не имеют доступа к закрытой части их базового класса. Элементы data1 и function1 недоступны объекту aPrivateDerived1. Если в классе Base1 определены открытые функции для доступа к закрытым полям через объекты классов, то эти функции наследуются public-производными классами и могут использоваться объектами этих классов.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]