Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
лек_3_слайды.doc
Скачиваний:
1
Добавлен:
17.11.2019
Размер:
457.73 Кб
Скачать

Наследуемые производным классом

По определению указатель типа А может ссылаться на любой из этих объектов, поскольку они связаны отношением наследования.

ПРИМЕР

//можно присвоить адрес cObject //указателю на базовый класс p:

A *p;

//Объявить указателю на базовый класс p типа A*

p= &cObject;

// Присвоить p адрес сObject

Несмотря на то что указатель p типа А*, он может ссылаться на объект типа С, т.к. этот класс выведен из А.

Правило, возможно, будет понятнее вам, если вы будете думать о С, как об особом виде объекта А (так, золотая рыбка – особая разновидность рыб, но она все же остается рыбой).

эта взаимосвязь указателей работает только в одном направлении.

Объект типа С –особый вид объекта А, но объект типа А не является особым видом объектов В и С.

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

Этот принцип становится особенно важным, когда в связанных отношениями родства классах определяются виртуальные функции. Функции имеют точно такой же вид и программируются точно так же. Как и обычные функции, только их объявления предваряются ключевым словом virtual.

Например,

//класс А может объявлет //виртуальную функцию vf():

class A {

public:

Virtual void vf();

};

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

Она отличается от обычной функции-члена лишь добавлением ключевого слова virtual.

В классе может объявляться столько виртуальных функций, сколько потребуется.

Виртуальные функции м.б. открытыми, защищенными или закрытыми членами класса.

//В классе В, выведенном из А, также //м. объявить виртуальную функцию, //названую опять-таки vf():

class B: public A {

public:

Virtual void vf();

// Замещающая виртуальная функция

// в В замещает виртуальную функцию

//с тем же именем в А

};

Когда в классе, подобном В, определяется виртуальная функция, имеющая одинаковое имя с виртуальной функцией класса-предка, такая функция называется замещающей.

//В классе С также м. определить //замещающую функцию:

class C: public B {

public:

Virtual void vf();

};

В данном случае употреблять ключевое слово Virtual не обязательно, поскольку с находится в конце линии наследования.

Конечно, если еще один класс D будет выведен из класса С и в D потребуется заместит функцию vf(), то в с эта функция должна быть определена с ключевым словом Virtual.

Вернемся к указателю p типа А*, который ссылается на объект cobject типа С* внимательно присмотритесь к оператору, вызывающему виртуальную функцию vf() для объекта на который ссылается p:

p->vf();

Указатель p может хранить адрес объекта типа А, В или С.

во время выполнения этот оператор вызовет виртуальную функцию vf(), принадлежащую классу А, если p ссылается на объект типа А, оператор вызовет функцию vf(), принадлежащую классу В, если p ссылается на объект типа А

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

Виртуальные функции в реальной жизни

Еще один классический пример поможет уяснить их практическое значение в реальном мере программирования.

Вообразите, что вы пишете графическую программу и хотите разработать различные классы для таких фигур, как круги, квадраты и линии. Поскольку все эти классы взаимосвязаны (все они - фигуры), //сначала вы создаете базовый класс //shape следующим образом:

class Shape {

public:

// …. Разнообразные члены

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