Понимание экспозиции Александреску о слабостях множественного наследования

ОБНОВЛЕНИЕ: я задал более узкий вопрос здесь.

На страницах 6-7 Modern C++ Design Андрей Александреску дает очень фундаментальное обсуждение сильных и слабых сторон двух C++ языковые возможности - множественное наследование и шаблоны - в отношении создания гибких конструкций. Он делает вывод:

Теперь сравните список недостатков множественного наследования со списком недостатков шаблонов. Интересно, что множественное наследование и шаблоны способствуют дополнительным компромиссам. Множественное наследование имеет скудную механику; шаблоны имеют богатую механику. Множественное наследование теряет информацию о типе, которая изобилует шаблонами. Специализация шаблонов не масштабируется, но множественное наследование довольно хорошо масштабируется. Вы можете предоставить только одно значение по умолчанию для функции-члена шаблона, но вы можете написать неограниченное количество базовых классов.

Я чувствую, что то, что говорит здесь Андрей, очень важно, но я не могу понять, что говорится, без каких-либо примеров, иллюстрирующих эти моменты. Этот вопрос просит предоставить простые примеры, иллюстрирующие эти моменты (пожалуйста, продолжайте читать).

Чтобы сделать вопрос более конкретным, я хотел бы попросить сосредоточиться на слабостях множественного наследования. Вот что Андрей должен сказать о них (текст в квадратных скобках - мой согласно моему пониманию контекста):

В такой обстановке [т.е. множественное наследование], [для создания гибкого SmartPtr,] пользователь будет создавать многопоточный класс интеллектуальных указателей с подсчетом ссылок, наследуя некоторые BaseSmartPtr класс и два класса: MultiThreaded а также RefCounted, Любой опытный дизайнер класса знает, что такой наивный дизайн не работает.

Анализ причин, по которым множественное наследование не позволяет создавать гибкие конструкции, дает интересные идеи для достижения надежного решения. Проблемы с сборкой отдельных функций с использованием множественного наследования заключаются в следующем:

  1. Механика Не существует стандартного кода для сборки унаследованных компонентов контролируемым образом. Единственный инструмент, который объединяет BaseSmartPtr, MultiThreaded и RefCounting, - это языковой механизм, называемый множественным наследованием. Язык применяет простую суперпозицию при объединении базовых классов и устанавливает набор простых правил для доступа к их членам. Это недопустимо за исключением самых простых случаев. В большинстве случаев вам необходимо тщательно координировать работу унаследованных классов, чтобы получить желаемое поведение.
  2. Введите информацию. Базовые классы не имеют достаточно информации о типах для выполнения своих задач. Например, представьте, что вы пытаетесь реализовать глубокое копирование для своего класса интеллектуальных указателей, производного от базового класса DeepCopy. Но какой интерфейс у DeepCopy? Он должен создавать объекты типа, которого он не знает.
  3. Государственная манипуляция. Различные поведенческие аспекты, реализованные с помощью базовых классов, должны манипулировать одним и тем же состоянием. Это означает, что они должны использовать виртуальное наследование для наследования базового класса, который содержит состояние. Это усложняет проект и делает его более жестким, поскольку исходная посылка состояла в том, что пользовательские классы наследуют библиотечные классы, а не наоборот.

Я был бы очень признателен за простой пример для каждого из трех пунктов выше. В каждом примере будет показано как одно ограничение множественного наследования (например, плохая механика), так и то, как шаблоны не обладают этим ограничением (Андрей писал, что "множественное наследование и шаблоны способствуют дополнительному компромиссу").

0 ответов

Другие вопросы по тегам