Для проекта я хочу скрыть некоторые детали реализации из интерфейса библиотеки. Единственный способ, которым я столкнулся с этим «эффективным» (с точки зрения кодирования и обслуживания), заключался в множественном наследовании абстрактных и конкретных базовых классов на основе одной и той же абстрактной базы. Итак, да, я закончил с расширенной структурой алмазов.C++ множественное наследование/виртуальное наследование
Я обычно стараюсь избегать множественного наследования, когда это возможно, из-за его осложнений, поэтому я не очень разбираюсь в его использовании, и поэтому я не уверен, что проект, с которым я перебираюсь, имеет некоторые подводные камни, Наблюдаю.
В основном мне нужно предоставить несколько «инструментов». Эти «инструменты» имеют, конечно, некоторые детали реализации, которые я хочу скрыть с помощью интерфейсных ABC, например:
класс Tool1Impl: public ITool1;
класс Tool2Impl: public ITool2;
Однако, конечно, инструменты имеют довольно общие черты.
Поэтому я хотел бы иметь общий базовый класс, но детали реализации снова должны быть скрыты через интерфейсы.
я придумал следующее (алмаз) схеме:
ITool
/ | \
/ | \
/ | \
ITool1 ToolImplBase ITool2 ... IToolN
\ / \ /
\ / \ /
\ / \/
ToolImpl1 ToolImpl2 ... IToolImplN
ToolImplBase реализует чистую виртуальную функциональность ITool. ToolImpl1 реализует чистую виртуальную функциональность, объявленную в ITool1.
план реализации выглядит следующим образом:
class ITool {
public:
virtual int common_foo(int a) = 0;
};
class ITool1 : public virtual ITool {
public:
virtual int specific_foo(int b) = 0;
};
class ITool2 : public virtual ITool {
public:
virtual int specific_bar(int c) = 0;
};
class ToolImplBase : public virtual ITool {
public:
virtual int common_foo(int a) override;
protected:
int _some_common_data;
};
class ToolImpl1 : public ToolImplBase, public virtual ITool1 {
public:
virtual int specific_foo(int b) override;
private:
int _some_specific_data;
};
class ToolImpl2 : public ToolImplBase, public virtual ITool2 {
public:
virtual int specific_bar(int c) override;
private:
int _some_specific_data;
};
кажется, делать то, что я хочу, но я не уверен, если есть какие-либо потенциальные проблемы или очевидные проблемы с этим. Я также не уверен, правильно ли я получил «виртуальные» в схеме наследования (а не виртуальные методы, но «общедоступный виртуальный»). Одна проблема в том, что MSVC (я застрял с 2010 из-за некоторых внешних depencies в это время) дает мне предупреждение компилятора C4250:
warning C4250: 'ToolImpl1': inherits'ToolImplBase::ToolImplBase::common_foo' via dominance
Могу ли я просто игнорировать это? Я даже не уверен, почему я получаю это, потому что непримиримый способ «common_foo» является чисто виртуальным, поэтому на самом деле не существует допустимой «недоминирующей» реализации.
Спасибо за любой вход (для «никогда использования И.Р.», за исключением, я стараюсь избегать его, где это возможно, уже).
Мой маленький кусочек: не стесняйтесь использовать MI, когда это требуется, но если у вас есть алмаз, то вы, вероятно, на ложном пути. Вы уверены, что не используете наследование из-за результатов вместо смысла? Две вещи, которые следует учитывать для ToolImplBase (я не могу сказать больше, потому что пример вымышленный): состав и частное наследование. –
Пример не в том, что вымышленный, это из моего фактического кода, конечно, упрощенного. Как бы вы использовали композицию здесь? Просто делегирование всех общих функций из ITool в ToolImplFoo в содержащуюся ToolImplBase? –
Функция 'common_foo' C4250 наследуется по 2 пути и имеет разную реализацию, ее необходимо реализовать в окончательной форме. – Danh