Class B class C

Class A

Func()

Func () Func()

class A {

public:

virtual void Func ();

};

class B: public A {

virtual void Func();

};

class C: public A {

virtual void Func();

};

void A:: Func() {cout<<”A”; }

void B:: Func() {cout<<”B”; }

void C:: Func() {cout<<”C”; }

// Создадим указатель на базовый класс А (не создавая объекта)

// и два объекта типов В и С

void main () {

A* ap;

B* bp = new B;

C* cp = new C;

// в зависимости от значения указателя будет вызываться та или иная виртуальная //функция

ap = bp;

ap->Func(); // вызывается функция B:: Func()

ap =cp;

ap->Func(); // вызывается функция C:: Func()

}

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

void F (A* a) { a->Func(); }

void main () {

A* ap;

B* bp = new B;

C* cp = new C;

ap = bp;

F(ap); // в F вызывается B:: Func()

ap = cp;

F(ap); // в F вызывается C:: Func()

3. Передавать в функцию F() можно не только указатель на базовый класс, но и ссылку на базовый класс:

void F (A& a) { a. Func(); }

void main () {

A* ap;

B* bp = new B;

C* cp = new C;

ap = bp;

F(*ap); // в F вызывается B:: Func()

ap = cp;

F(*ap); // в F вызывается C:: Func()

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

void F (A* a) { a->Func(); }

void main () {

B b;

C c;

A* ap;

ap = &b;

F(ap); // в F вызывается B:: Func()

ap = &c;

F(ap); // в F вызывается C:: Func()

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

void main () {

A* bp = new B;

A* cp = new C;

bp->Func(); // вызывается функция B:: Func()

cp->Func(); // вызывается функция C:: Func()

cp=bp;

cp->Func(); // вызывается функция B:: Func()

6. Механизм виртуального вызова может быть подавлен с помощью использования полного квалифицированного имени.

7. Если базовый класс содержит хотя бы один виртуальный метод, то рекомендуется всегда снабжать этот класс виртуальным деструктором, даже если он ничего не делает. Наличие такого виртуального деструктора предотвратит некорректное удаление объектов производного класса, адресуемых через указатель на базовый класс, так как в противном случае деструктор производного класса вызван не будет.

Пустая и чистая виртуальные функции. Абстрактный класс.

Реально в конкретных задачах вызываются лишь функции производных классов. “Исходная” виртуальная функция базового класса часто нужна только для того, чтобы в производных классах было, что замещать.

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

class A {

public:

virtual void Func () { }

};

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

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

virtual int Func () { return 0;}

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

virtual int Func (int, char*) =0;

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

Объявление такой функции в базовом классе носит формальный характер для указания на виртуальность функций с данным именем.

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

Свойства абстрактного класса:

- Невозможно создать самостоятельных объектов абстрактного класса.

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

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

Если замещение не производится, то производный класс также является абстрактным.

Class A { // абстрактный класс

public:

virtual int Func (char*) =0;

void F ();

};

class B: public A { // В - не абстрактный класс


Понравилась статья? Добавь ее в закладку (CTRL+D) и не забудь поделиться с друзьями:  



double arrow
Сейчас читают про: