Лучшее - это: не имеющий одинаковых имен функций в обоих интерфейсах , создание выходных параметров возвращаемых значений безусловно, является интересной альтернативой. Для полноты: давайте предположим, что мы не можем изменить интерфейсы базовых классов, возможно, из-за того, что они поступают из разных библиотек & ndash; и нам все еще нужно переопределить.
Ну, во-первых: наследование обоих интерфейсов вообще может быть сомнительным проектом, очень вероятно, что вы нарушите принцип единственной ответственности .
Теперь давайте предположим, что нам нужно в любом случае. Тогда возможный обходной путь (он не соответствует моему собственному определению «элегантности» - но по крайней мере ...) - это промежуточные классы:
class BaseA { virtual ~BaseA(); virtual void foo(); };
class BaseB { virtual ~BaseB(); virtual int foo(); };
class DerivedA : public BaseA { void foo() override; };
class DerivedB : public BaseB { int foo() override; };
class Derived : public DerivedA, public DerivedB { };
Теперь Derived
может служить как BaseA
, так и BaseB
и все еще имеет переопределенные оба (в данном случае) варианта foo, хотя и косвенно.
Если вы намереваетесь продолжить наследование от Derived
, все еще позволяя переопределить любой вариант функции foo
, то каждое переопределение в DerivedA
и DerivedB
само вызовет (новую) виртуальную функцию fooA
и fooB
соответственно:
class DerivedA : public BaseA
{
public:
void foo() final // better than override:
// prevents breaking the pattern again
{ fooA() };
protected:
virtual void fooA() = 0;
};
class DerivedB : public BaseB
{
public:
int foo() final { return fooB() };
protected:
virtual int fooB() = 0;
};
Этот же трюк позволяет переопределениям использовать члены обеих баз и, безусловно, является чистым подходом для решения этой проблемы, однако он имеет некоторый компромисс, поскольку вызовы виртуальных функций не приходят бесплатно (поиск в таблице, затем фактический вызов функции) & ndash; поэтому, если производительность важнее (подумайте, если она действительно !), вы можете просто реализовать переопределения в DerivedA
и DerivedB
напрямую.