Московский государственный университет имени М.В.Ломоносова
Опубликован: 01.11.2004 | Доступ: свободный | Студентов: 11275 / 456 | Оценка: 4.12 / 4.01 | Длительность: 19:20:00
ISBN: 978-5-9556-0077-9
Специальности: Программист
Лекция 12:

C++: статические члены класса и виртуальные функции

< Лекция 11 || Лекция 12: 123 || Лекция 13 >

Виртуальные методы

Виртуальные методы объявляются в базовом классе с ключевым словом virtual, а в производном классе могут быть переопределены. Прототипы виртуальных методов как в базовом, так и в производном классе должны быть одинаковы.

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

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

При вызове метода с использованием указателя на класс действуют следующие правила:

  • для виртуального метода вызывается метод, соответствующий типу объекта, на который указывает указатель.
  • для не виртуального метода вызывается метод, соответствующий типу самого указателя.

В следующем примере иллюстрируется вызов виртуальных методов:

class A                          // Объявление базового класса
{ public:
    virtual void VirtMetod1();   // Виртуальный метод
    void Metod2();               // Не виртуальный метод
};
void A::VirtMetod1() { cout << "Вызван A::VirtMetod1\n";}

void A::Metod2() { cout << "Вызван A::Metod2\n"; }

class B : public A         // Объявление производного класса
{public:
    void VirtMetod1();     // Виртуальный метод
    void Metod2();         // Не виртуальный метод
};
void B::VirtMetod1() {    cout << "Вызван B::VirtMetod1\n";}
void B::Metod2() {  cout << "Вызван B::Metod2\n"; }
void main() {
    B aB;                   // Объект класса B
    B *pB = &aB;        // Указатель на объект класса B
    A  *pA    = &aB;    // Указатель на объект класса A
    pA->VirtMetod1();    // Вызов метода VirtMetod класса B
    pB->VirtMetod1();    // Вызов метода VirtMetod класса B
    pA->Metod2();        // Вызов метода Metod2 класса A
    pB->Metod2();        // Вызов метода Metod2 класса B
}
Пример 12.1. Вызов виртуальных методов

Результатом выполнения этой программы будут следующие строки:

Вызван B::VirtMetod1
Вызван B::VirtMetod1
Вызван A::Metod2
Вызван B::Metod2

Чисто виртуальной функцией называется виртуальная функция, указанная с инициализатором

=0.

Например:

virtual void F1( int) =0;

Объявление класса может содержать виртуальный деструктор, используемый для удаления объекта определенного типа. Однако виртуального конструктора в языке С++ не существует. Некоторой альтернативой, позволяющей создавать объекты заданного типа, могут служить виртуальные методы, в которых выполняется вызов конструктора для создания объекта данного класса.

Например:

class A{
public:
    A();
    A (const A&);
    virtual A* virt_object1 () {
	    return new A();
	}
    virtual A* virt_object2 () {
	    return new A(*this);
	}
}

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

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

Например:

class A : virtual public B  {   }

Абстрактные классы

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

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

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

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

< Лекция 11 || Лекция 12: 123 || Лекция 13 >
Александр Демьяненко
Александр Демьяненко

Можно ли сдавать один и тот же тест несколько раз?
Или же один и тот же тест можно сдать лишь однажды?

Максим Стогний
Максим Стогний

Добрый день!

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

тип_метода (имя_класса::*имя_метода_указателя)
    (список параметров);
тип_функции (*имя_ функции_указателя)
    (список параметров);

при этом можно было  тип_функции во втором описании заменить на тип_метода? Т.е.:

тип_метода (*имя_ метода_указателя)
    (список параметров);