« : Июль 16, 2013, 11:53:39 am »
"Интервью с создателем C++ STL, 1995 г."
часть 1,
часть 2Вместе с Дейвом Мюссером мы начали работу над созданием Ada-библиотеки. Это было существенным обстоятельством, т.к. переключение с динамически типизированного языка, такого как Scheme, к строго типизированному языку, такому как Ada, позволило мне осознать важность строгой типизации. Все понимают, что строгая типизация помогает в поиске ошибок. Я обнаружил, что строгая типизация в контексте дженериков языка Ada (обобщённых процедур — т.е. применимых к любому типу), также являлась инструментом выявления моделей. Она являлась не только инструментом для вылавливания ошибок. Она также была инструментом для размышления. Эта работа привела меня к идее ортогональной декомпозиции пространства компонентов. Я осознал, что программные компоненты принадлежат разным категориям. Приверженцы ООП думают, что всё является объектом. Когда я работал над обобщённой библиотекой для Ada, я осознал, что это не так. Есть вещи, являющиеся объектами. Вещи, которые имеют состояние и изменяют свое состояние, являются объектами. И в то же время существуют вещи, не являющиеся объектами. Бинарный поиск — это не объект. Это алгоритм. Более того, я осознал, что, декомпозируя пространство компонентов на несколько ортогональных измерений, мы можем уменьшить число компонентов, и, что более важно, мы можем предоставить концептуальную основу того, как проектировать что-либо.
Затем мне была предложена работа в Лаборатории Белла в группе языка C++ над библиотеками C++. Они спросили меня, мог бы я сделать то же на C++. Конечно, я не знал C++, и конечно же я ответил согласием. Но я не мог сделать этого на C++, т.к. в 1987 г. C++ не имел шаблонов, которые необходимы для этого стиля программирования. Наследование было единственным механизмом для получения обобщённости, и он не был достаточным.
Даже сейчас наследование в C++ не представляет особой ценности для обобщённого программирования. Давайте обсудим, почему. Многие пытались использовать наследование для реализации структур данных и контейнерных классов. Как нам известно теперь, было очень мало успешных попыток, если таковые вообще были. Наследование C++ и стиль программирования, связанный с ним, являются существенно ограниченными. Так, в нём невозможно реализовать дизайн, который включает такую простую вещь, как использование оператора сравнения на равенство. Если вы начинаете с базового класса X в качестве корня вашей иерархии и определяете для этого класса виртуальный оператор сравнения на равенство, получающий аргумент типа X, то далее унаследуйте класс Y от X. Каков интерфейс оператора сравнения на равенство? Он имеет равенство, которое сравнивает Y с X. Используя в качестве примера животных (объектно-ориентированные люди любят животных), определите «млекопитающее» и унаследуйте «жирафа» от млекопитающего. Затем определите функцию-член «спариваться», в которой одно животное спаривается с другим и возвращает животное. Затем вы выводите «жирафа» из животного и, конечно, он имеет функцию «спариваться», в которой жираф спаривается с животным и возвращает животное. Это определенно не то, что вам бы хотелось. В то время как спаривание может быть не очень важным для C++-программистов, оператор равенства является таковым. Я не знаю ни одного алгоритма, в котором не использовалась бы некоторая разновидность сравнения на равенство.
Вам нужны шаблоны, чтобы иметь дело с подобными проблемами. Вы можете иметь шаблонный класс «Животное», имеющий функцию-член «спариваться», которая принимает животное и возвращает животное. Когда вы инстанцируете «Жирафа», «спариваться» сделает верные действия. В связи с этим шаблон является более мощным механизмом.
![](http://oberspace.org/Themes/default/images/ip.gif)
Записан
to iterate is human, to recurse, divine
Салат «рекурсия»: помидоры, огурцы, салат…