Derived_1 d1;
Derived_2 d2;
Base_ *ptr;
ptr = &d1;
ptr->SetParameters(one argument)
ptr = &d2;
ptr->SetParameters(one or two arguments)
Способ написания этого кода подразумевает, что вы обладаете знаниями о двух вещах:
- во время первого вызова
SetParameters()
, ptr
указывает на объект типа Derived_1
- при втором вызове указывает на объект типа
Derived_2
.
Это, в свою очередь, означает, что вам известны типы stati c - - и на самом деле вам нужно из-за разных подписей.
Для такого сценария динамический полиморфизм c не является правильным выбором, потому что он предполагает, что вы можете общаться с различными реализациями (переопределенными методами), используя унифицированный доступ (вызов метода виртуальной базы).
Итак, если вы обладаете этими знаниями во время компиляции, просто используйте вызовы не виртуальных методов .
Тем не менее, существуют похожие сценарии ios, в которых вы можете быть заинтересованы в поддержке разных подписей во время выполнения , например, если вы загружаете конфигурацию динамически. Вот пример, где не число , а типы аргументов отличаются.
class Car : public Vehicle
{
virtual void addFuel(const Petrol& f) override;
};
class Airplane : public Vehicle
{
virtual void addFuel(const Kerosene& f) override;
};
Как бы тогда выглядела базовая функция?
class Vehicle
{
virtual ~Vehicle() {} // don't forget this!
virtual void addFuel(const /* which type? */& f) = 0;
};
Один из вариантов - сделать тип топлива иерархией (и Kerosene
, и Petrol
наследуют класс Fuel
):
class Vehicle
{
virtual ~Vehicle() {}
virtual void addFuel(const Fuel& f) = 0;
};
Однако в этом случае каждый реализация должна либо полагаться на тот факт, что оно прошло правильное топливо, либо проверить тип во время выполнения.
class Airplane : public Vehicle
{
virtual void addFuel(const Fuel& f) override
{
if (auto* k = dynamic_cast<const Kerosene*>(&f))
{
// use concrete fuel
}
}
};