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

33. Чисто виртуальные функции и абстрактные классы. Вызов чисто виртуальной функции в конструкторе до завершения инициализации объекта.

Намерение создать виртуальный метод лишь ради его интерфейса и последующего замещения в производных классах можно выразить явно при помощи чисто виртуальных функций(pure virtual functions).

Сделать виртуальную функцию чисто виртуальной можно,

добавив инициализатор = 0:

virtual float getMaxExtraWeight () const = 0;

“Присвоение нуля” при объявлении является не более чем синтаксической иллюзией. Такие объявления по-прежнему вводят записи в таблицу виртуальных функций. Более того, теперь производные классы должны обязательно переопределять такие чисто виртуальные методы, иначе их объекты не смогут быть созданы.

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

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

class A

{

public:

A ()

{

A * pA = this;

pa->f(); // Эй, вообще-то объект пока недоконструирован!

}

virtual void f () = 0;

};

class B : public A

{

public:

B () {}

void f () override {}

};

B b;

В момент выполнения конструктора абстрактного класса, таблица виртуальных функций содержит специальную запись (__purecall) вместо неопределенной функции f:

Поведение этой функции состоит в генерации фатальной ошибки:

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

Попытка квалифицированного вызова чисто виртуальной функции приведет к ошибке на этапе компоновки:

class A

{

public:

virtual void f () = 0;

};

class B : public A

{

public:

void f () override

{

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

A::f();

}

};

error: unresolved external symbol "public: virtual void __thiscall A::f(void)" (?f@A@@UAEXXZ)

Невероятно, но факт - чисто виртуальные функции могут иметь тело:

class A

{

public:

// Чисто виртуальная функция - с телом!!!

virtual void f () = 0

{

std::cout << “I have a body, although I’m pure virtual” << std::endl;

}

};

class B : public A

{

public:

void f () override

{

// Вызов чисто виртуальной функции

A::f();

// Сделать что-либо еще:

// ...

}

};

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

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