Беда с разными видами полиморфизма

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

class base {
public:
void Print() {
std::cout << "This is parent class\n";
}
};

class derived : public base {
public:
void Print() {
std::cout << "This is derived class\n";
}
};

Если я сделаю это:

base b1;
b1.Print();
derived d1;
d1.Print();

результат довольно очевиден:

This is parent class
This is derived class

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

base b1;
derived d1;
base* pb = &b1;
base* pb2 = &d1;
pb->Print();
pb2->Print();

Выход будет:

This is parent class
This is parent class

Это связано с ранним связыванием, компилятор проверяет тип объекта, вызывающего функцию, а не тип объекта, который ее обрабатывает. И, очевидно, это делается во время компиляции. Теперь, если я использую virtual Ключевое слово в определении функции базового класса, то я могу легко сделать вышеупомянутое без каких-либо хлопот, что связано с поздним связыванием, которое сохраняет определение функции для времени выполнения на основе типа объекта, который ее обрабатывает. Это пример полиморфизма во время выполнения.

Извините, что занял слишком много времени, мой вопрос: разве это единственный способ достичь полиморфизма во время выполнения? Кроме того, если переопределение функции является полиморфизмом во время выполнения, то предыдущий пример (т.е. с ранним связыванием) также должен быть полиморфизмом во время выполнения, так как он также выполняет переопределение функции.

0

Решение

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

void foo(Base * _b)
{
if(_b->typeID == TID_BASE)
{
b->bar();
}
else if(_b->typeID == TID_DERIVED)
{
static_cast<Derived*>(_b)->bar();
}
}

Где идентификатор типа — это некоторая форма перечисления или указатель, который однозначно идентифицирует тип. Это сказало, Я бы никогда не рекомендовал делать это, если вы на самом деле не измерили, что это влияет на производительность вашего случая.

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

0

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector