Индивидуальные очистные сооружения: К классу индивидуальных очистных сооружений относят сооружения, пропускная способность которых...
Автоматическое растормаживание колес: Тормозные устройства колес предназначены для уменьшения длины пробега и улучшения маневрирования ВС при...
Топ:
Оснащения врачебно-сестринской бригады.
Оценка эффективности инструментов коммуникационной политики: Внешние коммуникации - обмен информацией между организацией и её внешней средой...
Установка замедленного коксования: Чем выше температура и ниже давление, тем место разрыва углеродной цепи всё больше смещается к её концу и значительно возрастает...
Интересное:
Искусственное повышение поверхности территории: Варианты искусственного повышения поверхности территории необходимо выбирать на основе анализа следующих характеристик защищаемой территории...
Аура как энергетическое поле: многослойную ауру человека можно представить себе подобным...
Отражение на счетах бухгалтерского учета процесса приобретения: Процесс заготовления представляет систему экономических событий, включающих приобретение организацией у поставщиков сырья...
Дисциплины:
2018-01-03 | 173 |
5.00
из
|
Заказать работу |
|
|
// Файл NoVirtF.cpp
#include <iostream.h>
struct base{ // Базовый класс base
void fun(int i) // Функция базового класса
{cout << "\n base::i= " << i;}
};
struct derive: public base{ // Производный класс derive
void fun(int i) // Функция производного класса
{cout << "\n derive::i= " << i;}
};
#include <conio.h>
void main()
{
base B, *pb = &B; // Объект base и указатель на base
derive D, *pd = &D; // Объект derive и указатель на derive
base* pbd = &D; // Указатель на base инициализируется
// адресом объекта derive
pb->fun(1); // Печатает base::i=1
pd->fun(5); // Печатает derive::i=5
pbd->fun(4); // Печатает base::i=4;
getch();
}
Указателю на базовый класс можно присвоить адрес объекта производного класса, т.к. в производном классе есть все члены, которые есть в базовом. Обратное невозможно, т.е. указателю на производный класс нельзя присвоить адрес объекта базового класса, т.к. в базовом классе, вообще говоря, нет всех компонент, которые есть в производном. Например:
base B; // Объект базового класса
derive *pd; // Указатель на производный класс
pd = &B; // Ошибка! Нельзя указателю на производный класс
// присвоить адрес объекта базового класса
Так как pbd есть указатель на базовый класс, при обращении
pbd -> fun(4);
вызывается функция базового класса base::fun(), а не функция производного класса derive::fun(), несмотря на то, что указатель pbd имеет значение адреса объекта производного класса.
Выбор нужной функции устанавливается при компиляции программы в соответствии с типом указателя, а не с его значением, которое может быть разным в разные моменты работы программы. Такой режим называется ранним или статическим связыванием.
Позднее или динамическое связывание обеспечивают виртуальные функции. Рассмотрим пример.
Программа 61. Виртуальные функции
// Файл VirtualF.cpp
|
#include <iostream.h>
struct base{ // Базовый класс base
virtual void vfun(int i) // Виртуальная функция базового класса
{cout << "\n base::i= " << i;}
};
struct derive1: public base{ // Производный класс derive1
void vfun(int i) // Переопределение виртуальной функции
{cout << "\n derive1::i= " << i;}
};
struct derive2: public base{ // Еще один производный класс derive2
void vfun(int i) // Переопределение виртуальной Функции
{cout << "\n derive2::i= " << i;}
};
#include <conio.h>
void main()
{
base B, *pb = &B; // Объект base и указатель на base
derive1 D1, *pd1 = &D1; // Объект derive1 и указатель на derive1
derive2 D2, *pd2 = &D2; // Объект derive2 и указатель на derive2
pb->vfun(1); // Печатает base::i=1
pd1->vfun(2); // Печатает derive1::i=2
pd2->vfun(3); // Печатает derive2::i=3
pb = &D1; // Изменяем значение указателя на базовый класс
pb->vfun(4); // Печатает derive1::i=4
pb = &D2; // Еще раз изменяем указатель на базовый класс
pb->vfun(5); // Печатает derive2::i=5
getch();
}
Интерпретация каждого вызова виртуальной функции через указатель на базовый класс зависит от значения указателя. В табл.28 указаны функции, вызываемые в зависимости от значения указателя.
Таблица 28. Вызовы виртуальной функции
Значение указателя pb | Функция, вызываемая инструкцией pb->vfun |
&B &D1 &D2 | base::vfun() derive1::vfun() derive2::vfun() |
Так как при компиляции программы невозможно предвидеть, какое значение примет указатель на базовый класс при работе программы, вопрос о выборе виртуальной функции решается на этапе выполнения программы и определяется значением указателя.
При вызове через указатель невиртуальной функции интерпретация определяется только типом, а не значением указателя.
Виртуальными могут быть только функции-члены класса.
В производном классе при объявлении виртуальной функции слово virtual можно не использовать, но лучше использовать, чтобы сделать программу более понятной.
Абстрактные классы
Абстрактным называется класс, в котором есть хотя бы одна чистая виртуальная функция. Чистой виртуальной функцией называется функция-член, которая имеет следующее определение:
|
virtual <ТИП><ИМЯ_ФУНКЦ>(<СПИСОК_ФОРМАЛЬН_ПАРАМ>) = 0;
Конструкция = 0 называется чистый спецификатор.
Следующая функция является чистой виртуальной:
virtual void fpure(void) = 0;
Чистая виртуальная функция ничего не делает и недоступна для вызовов. Она служит основой для подменяющих ее функций в производных классах.
Абстрактный класс может быть использован только как базовый класс для производных классов. Нельзя создавать объекты абстрактных классов. Механизм абстрактных классов разработан для представления общих понятий, которые в дальнейшем предполагается конкретизировать. Эти общие понятия, обычно, невозможно использовать непосредственно. Например, можно говорить об общем понятии «фигура» на плоскости. Это понятие включает свойства, присущие любой конкретной фигуре: треугольнику, прямоугольнику, окружности. Например, у любой фигуры есть свойство цвет. Но изобразить можно всегда только конкретную фигуру, а не фигуру вообще.
|
|
Таксономические единицы (категории) растений: Каждая система классификации состоит из определённых соподчиненных друг другу...
Адаптации растений и животных к жизни в горах: Большое значение для жизни организмов в горах имеют степень расчленения, крутизна и экспозиционные различия склонов...
Эмиссия газов от очистных сооружений канализации: В последние годы внимание мирового сообщества сосредоточено на экологических проблемах...
История развития пистолетов-пулеметов: Предпосылкой для возникновения пистолетов-пулеметов послужила давняя тенденция тяготения винтовок...
© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!