Проверка ошибок при использовании виртуальных функций

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

class P {

public:

P(void){}

virtual void hello(void) {}

};

class C: public P {

public:

C(void) {}

virtual void hello(void) { cout << “Hello world”; }

};

void main() {

P *p; C c;

p=&c;

p->hello(“Hello”); // ошибка

}

Компилятор выдаст ошибку на строке p->hello(“hello”). Компилятор может определить, что виртуальная функция hello не имеет параметров, даже если сообщение связывается с методом hello класса C во время выполнения программы. Виртуальные функции, определенные в родительском или потомственных классе имеют одинаковые списки параметров, так как позднее связывание не оказывает влияния на контроль типов параметров.

Техническая реализация виртуальных функций

Объект С++ представляет собой непрерывный участок памяти. Указатель на такой объект содержит начальный адрес этого участка. Когда вызывается функция-член (объекту посылается сообщение), этот вызов транслируется в обычный вызов функции с дополнительным аргументом, который содержит указатель на объект.

Например,

ClassName *object;

object->message(10);

преобразуется в

ClassName_message(object,10);

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

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

class P {

int value;

public:

virtual int method1(float r):

virtual void method2(void);

virtual float method3(char *s);

};

class C1:public P {

public:

void method2(void);

};

class C2: public C1 {

public:

float method3(char *s);

};

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

Типичный объект, приведенных выше классов, выглядит, примерно, так:

int value;

virtual_table->P::method1

C1::method2

C2::method3

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

С2 *с;

c->method3(“Hello”);

преобразуется в

(*(c->virtual_table[2]))(c,”Hello”);


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



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