Главная Случайная страница


Полезное:

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


Категории:

АрхитектураАстрономияБиологияГеографияГеологияИнформатикаИскусствоИсторияКулинарияКультураМаркетингМатематикаМедицинаМенеджментОхрана трудаПравоПроизводствоПсихологияРелигияСоциологияСпортТехникаФизикаФилософияХимияЭкологияЭкономикаЭлектроника






Виртуальные функции





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

Член-функция может быть объявлена виртуальной при следующих условиях:

- класс, содержащий виртуальную функцию, будет базовым в иерархии порождения;

- реализация функции зависит от класса и будет разной в каждом порожденном классе.

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

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

Пример.

сlass student

{...

public:

virtual void vivod();

};

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

virtual <тип> <имя_функции>

(<список формальных параметров>)=0;

Чистая виртуальная функция ничего не делает и недоступна для вызовов, еe назначение - служить основой для подменяющих ее функций в производных классах.

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

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

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

Полиморфная операция - операция, которая имеет много значений, зависящих от типа объекта, с которым операция связывается на этапе выполнения программы.

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

Одно из преимуществ абстрактного метода является чисто концептуальным: программист может мысленно наделить нужным действием абстракцию сколь угодно высокого уровня.

Пример. Для геометрических фигур мы можем определить метод Draw(), который их рисует: треугольник TTriangle, окружность TCircle, квадрат TSquare. Мы определим аналогичный метод и для абстрактного родительского класса TGraphObject. Однако такой метод не может выполнять полезную работу, поскольку в классе TGraphObject нет достаточной информации для рисования чего бы то ни было. Тем не менее, присутствие метода Draw() позволяет связать функциональность (рисование) только один раз с классом TGraphObject, а не вводить три независимые концепции для подклассов TTriangle, TCircle, TSquare.

Имеется и вторая, более актуальная причина использования абстрактного метода. В объектно-ориентированных языках программирования со статическими типами данных, к которым относится и C++, программист может вызвать метод класса, только если компилятор может определить, что класс действительно имеет такой метод.

Пример. Предположим, что программист хочет определить полиморфную переменную типа TGraphObject, которая будет в различные моменты времени содержать фигуры различного типа. Это допустимо для полиморфных объектов. Тем не менее, компилятор разрешит использовать метод Draw() для переменной, только если он сможет гарантировать, что в классе переменной имеется этот метод. Присоединение метода Draw() к классу TGraphObject обеспечивает такую гарантию, даже если метод Draw() для класса TGraphObject никогда не выполняется. Естественно, для того чтобы каждая фигура рисовалась по-своему, метод Draw() должен быть виртуальным.

Правила определения виртуальных функций.

1. Если в базовом классе впервые объявлена виртуальная функция, то она должна быть либо чистой виртуальной, либо для нее должно быть задано определение.

2. Если в базовом классе объявлена чистая виртуальная функция, то в порожденном классе должно быть задано определение этой функции, либо функция должна быть вновь объявлена как чистая виртуальная. Язык не разрешает наследование по умолчанию чистой виртуальной функции.

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

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

Пример.

class Base

{

public:

virtual void print();

};

class First: public Base

{

public:

void print();

};

class Second: public Base

{

public:

void print();

};

int main()

{

Base *mas[2];

First obj1;

Second obj2;

mas[0]=&obj1;

mas[1]=&obj2;

for(int i=0; i<2; i++)

(*mas[i]).print();

}

Видимость виртуальных функций.

Виртуальная функция вызывается через указатель или ссылку на базовый класс, следовательно; виртуальный вызов функции будет иметь такую видимость, с которой функция объявлена в базовом классе.

Date: 2016-05-13; view: 428; Нарушение авторских прав; Помощь в написании работы --> СЮДА...



mydocx.ru - 2015-2024 year. (0.007 sec.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав - Пожаловаться на публикацию