Вы думаете, как OOP программист, пытаясь создавать абстрактные модели вещей. Многократное наследование C ++, как и многие другие вещи в C ++, - это инструмент , который имеет особый эффект. Относится ли это к какой-либо модели OOP, не имеет значения, если использовать утилиту самого инструмента. Иными словами, вам не нужна «модель реального мира», чтобы оправдать не виртуальное наследование; вам просто нужен реальный сценарий использования .
Поскольку производный класс наследует членов базового класса, наследование часто используется в C ++ как средство сбора набора общих функций. вместе, иногда с минимальным взаимодействием с производным классом и введением этой функциональности непосредственно в производный класс.
Шаблон любопытного повторяющегося шаблона и другие миксиноподобные конструкции являются механизмами для этого. Идея состоит в том, что у вас есть базовый класс, который является шаблоном, а его параметр шаблона является классом производного , который его использует. Это позволяет базовому классу иметь некоторый доступ к самому производному классу без функций virtual
.
Самый простой пример, который я могу вспомнить в C ++, - это enable_shared_from_this
, который позволяет объекту, время жизни которого в настоящее время управляется shared_ptr
для фактического получения shared_ptr
для этого объекта только из указателя / ссылки на этот объект. При этом используется CRTP для добавления различных членов и интерфейсов, необходимых для обеспечения возможности shared_from_this
в производном классе. А так как наследование является publi c, оно также позволяет различным функциям shared_ptr
, которые "позволяют shared_from_this" обнаруживать, что в конкретном типе есть элемент shared_from_this
, и правильно его инициализировать.
enable_shared_from_this
не нуждается в виртуальном наследовании и, вероятно, с ним не очень хорошо будет работать.
Теперь представьте, что у меня есть какой-то другой класс CRTP, который внедряет некоторые другие функции в объект. Эта функциональность не имеет ничего общего с shared_ptr
, но использует CRTP и наследование.
Хорошо, если я сейчас напишу какой-то тип, который хочет наследовать как от enable_shared_from_this
, так и от этого другого функциональность, ну, это работает просто отлично. Нет необходимости в виртуальном наследовании, и в действительности это только усложнит композицию.
Виртуальное наследование не является бесплатным. Это фундаментально меняет кучу вещей о том, как тип относится к своим базовым классам. Если вы наследуете от такого типа, ваши конструкторы должны инициализировать любые виртуальные базовые классы напрямую . Компоновка такого типа очень странная и вряд ли будет стандартизирована. И разные другие вещи. C ++ старается не заставлять программистов платить за функциональность, которой они не пользуются, поэтому, если вам не нужны специальные свойства виртуального наследования, вам не следует его использовать.