Строго говоря, вы не можете сделать это в C ++ - список параметров метода (и типы этих параметров) считаются частью сигнатуры метода , и поэтомуВиртуальный метод дочернего класса может переопределить / реализовать виртуальный метод родительского класса, только если они оба имеют одинаковое имя и одинаковые точные параметры.
Тем не менее, вы можете сортировать его, передавая аргументы, используя данные.структура, а не напрямую.Например:
class Base {
protected:
virtual void function(const std::map<std::string, std::variant> & args) = 0;
}
С учетом вышесказанного у вас есть метод, который может принимать любой набор именованных аргументов в форме набора пар ключ-значение.Затем дочерние классы (и их вызывающие) должны были согласовать, какие имена аргументов и значения аргументов использовать.Недостатком этого подхода является то, что он менее эффективен и сложнее в использовании (вызывающий должен создавать и заполнять std::map
каждый раз, когда он хочет вызвать метод, а метод должен проверять содержимое std:map
и рисунокчто с ними делать);однако если гибкость является вашей главной задачей, а производительность - нет (например, потому что метод не будет вызываться очень часто), этот подход может работать хорошо.
Другой подход заключается в использовании множественного наследования и указанииотдельные интерфейсы для каждого из двух методов и (просто для удобства) также интерфейсный класс для подклассов, которые хотят реализовать оба:
class BaseFirst {
protected:
virtual void function(arg_set_first) = 0;
}
class BaseSecond {
protected:
virtual void function(arg_set_second) = 0;
}
class BaseBoth : public BaseFirst, public BaseSecond {
};
class Derived_First: public BaseFirst {
private:
virtual void function(arg_set_first) {...}
};
class Derived_Second: public BaseSecond {
private:
virtual void function(arg_set_second) {...}
};
class Derived_Both: public BaseBoth {
private:
virtual void function(arg_set_first) {...}
virtual void function(arg_set_second) {...}
};
Поскольку любой конкретный фрагмент вызывающего кода знает, какой из function
методы, которые он захочет вызвать (и которые он не будет), он может просто указать соответствующие типы указателей / ссылок в своем API (например, BaseFirst *
, BaseSecond *
или BaseBoth *
), чтобы отразить его требования, иКомпилятор гарантирует вам, что только объекты, которые действительно соответствуют этим требованиям, могут быть переданы ему.