Класс не должен быть выведен больше чем из одного базового класса, который не является интерфейсным классом
Класс не должен быть выведен больше чем из одного базового класса, который не является интерфейсным классом.
Если класс наследовался нескольким неинтерфейсным классам, класс по существу имеет доступ к нескольким реализациям. Поддержание кода может затруднить.
Когда класс наследовался нескольким неинтерфейсным классам, существует вероятность, что та же функция членства существует в тех базовых классах и должна быть заменена в производном классе. Вероятность увеличивается, когда те базовые классы сами наследовались общему базовому классу (ромбовидная структура).
Предположим, интерфейсный класс Interface
имеет две конкретных реализации, Impl1
и Impl2
, и класс Final
выводит из обеих реализаций. Иерархия классов имеет эту ромбовидную структуру.
Следующие проблемы могут произойти:
Переопределения потребовали в итоговом производном классе для разрешения неоднозначности:
Обе реализации Impl1
и Impl2
имейте копию всех методов класса Interface
. Снять неоднозначность, какая копия может быть названа через Final
объект, вы обычно создаете еще одно переопределение всех методов в Final
класс, где вы вызываете обе копии явным образом с помощью оператора разрешения области видимости ::
(или одна копия, если вы выбираете). Смотрите пример ниже.
Каждый раз вы добавляете новую чистую виртуальную функцию в класс Interface
, необходимо не только создать реализации в мгновенных производных классах, но также и отслеживать целую иерархию классов и создать переопределения тех реализаций в классе Final
.
Если исходный класс Interface
не интерфейсный класс, проблема является четной более острая. Если наследования не являются виртуальными, две копии методов Interface
неявно сделаны в Impl1
и Impl2
(ромбовидная проблема).
Итоговый производный класс, ответственный за инициализацию всех классов в иерархии:
Чтобы избежать двойных инициализаций во множественном наследовании, стандарт C++ требует, чтобы вы вызвали конструкторов всех предыдущих классов в большей части производного класса.
В предыдущем примере, Final
конструктор класса не только должен вызвать конструкторов Impl1
и Impl2
но также и конструктор их родительского класса Interface
. Необходимо проследить вне непосредственных родителей, чтобы определить который конструкторы вызвать в итоговом производном классе.
Эти проблемы исчезают, если множественные наследования ограничиваются ситуациями, где класс может вывести из нескольких классов, но только один из них может быть неинтерфейсным классом. Интерфейсный класс является классом, который имеет только чистые виртуальные функции и элементы данных, которые являются константами времени компиляции (статический, contexpr
S. Класс не имеет никакой и собственной цели состояния, должен быть реализован производными классами.
Множественное наследование было спроектировано для ситуаций, где класс расширяет одну конкретную реализацию, но также и реализовывает другие идеи, представленные интерфейсными классами. Другое использование множественного наследования может привести к опасностям обслуживания.
Средство проверки отмечает множественные наследования, где больше чем один базовый класс является неинтерфейсным классом.
Интерфейсный класс является тем, который имеет только чистые виртуальные функции и элементы данных, которые являются константами времени компиляции (статический, contexpr
S. Любой конструктор или деструктор установлены в =default
или =delete
.
Если вы ожидаете нарушение правила, но не видите его, обратитесь к Кодированию Стандартных Нарушений, Не Отображенных.
Группа: Производные классы |
Категория: необходимый, автоматизированный |