Метод перегрузки в производном классе против множественной диспетчеризации

Согласно Википедии, Многократная отправка когда

… функция или метод могут отправляться динамически в зависимости от типа времени выполнения (динамического) нескольких аргументов.

Однако в C ++ я могу переопределить функцию в производном классе:

#include <iostream>

using namespace std;

class Base
{
public:
virtual void method(int a) { cout << a; }
virtual void method(int a, int b) { cout << a + b; }
};

class Derived: public Base
{
void method(int a) { cout << a * 10 << endl; }
void method(int a, int b) { cout << (a + b) * 10 <<endl; }
};

int main()
{
Base* derived = new Derived;
derived->method(1);
derived->method(1, 2);
return 0;
}

Здесь method привязан во время выполнения (потому что я использую virtual) и конкретный метод выбирается на основе входных параметров. Чем он отличается от описания множественной отправки в Википедии?

Вторичный вопрос: В чем преимущество (если есть) языков, которые поддерживают множественную диспетчеризацию, если такая комбинация полиморфизма и перегрузки методов существует в C ++?

1

Решение

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

В вашем конкретном случае это означает, что для вызова derived->method(1);компилятор смотрит на статические типы получателя (Base) и фактических аргументов (int). Затем он ищет среди всех методов Base (наследуется или объявляется в Base) для того, который подходит лучше всего; это Base::method(int), Во время выполнения система времени выполнения смотрит на динамический тип получателя (Derived) для наиболее конкретного метода, который переопределяет Base::method(int), который Derived::method(int)и вызывает этот метод с заданным фактическим аргументом (1).

Аналогично для второго звонка.

3

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

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

Выбор перегрузки на основе количества и (статического) типа других аргументов выполняется во время компиляции.

4

Это не множественная диспетчеризация, поскольку выбор во время выполнения выполняется только на основе одного параметра: типа объекта «производный». Разрешение перегрузки функции обрабатывается во время компиляции.

1

virtual void Base::method(int a);

можно рассматривать как

/*virtual*/ void method(Base&, int a);

Итак, в вашем случае у вас есть

derived->method(1); будет отправлять между:

/*virtual*/ void method(Base&, int a);
/*virtual*/ void method(Derived&, int a);

А также derived->method(1, 2); будет отправлять между:

/*virtual*/ void method(Base&, int a, int b);
/*virtual*/ void method(Derived&, int a, int b);

И в обоих случаях отправляется только по одному аргументу.

С

void method2(Base&, Base&);
void method2(Derived&, Base&);
void method2(Base&, Derived&);
void method2(Derived&, Derived&);

Если вы этого хотели (с Base* derived = new Derived)
method2(*derived, *derived); звонки void method2(Derived&, Derived&);
тогда это требует многократной отправки.
(В настоящее время он называет void method2(Base&, Base&);).

1
По вопросам рекламы [email protected]