ООП. Часть 3. С++. 👨‍🎓👨‍💻



В прошлых сериях мы познакомились с языками Simula и Smalltalk. Без лишней скромности можно сказать, что именно эти два ЯП являются родителями объектно-ориентированной парадигмы программирования. Ну а сегодня у нас в меню будет С++.



Прежде чем говорить про С++, следует вспомнить про Simula. Это был первый ОО ЯП в мире, который значительно опередил своё время (вышел в 67 году). ЯП ввел понятие класса, экземпляра, наследования, виртуальных методов, полиморфизма подтипов. Экземпляры классов всегда передавались по ссылке. Для управления памятью использовался Mark&Sweep сборщик мусора. Язык был реализован в виде интерпретатора и компилятора.



Дизайн Simula был основан на Algol в который была интегрирована ОО парадигма. Следовательно, у нас есть объектные и не-объектные типы. Причем, если тип - не объект, то и никаких методов на нем вызывать нельзя. Никаких "оберток" как в Java или JS.



Что еще можно сказать про Simula? Несмотря на все свои преимущества ЯП не снискал популярности. На мой взгляд главная причина тому недостаточная эффективность реализации для того времени. Это был 67 год и компьютеры тогда были дорогими и маломощными, а новые абстракции имели свою цену. И тут выбор падал скорее в сторону С, который хоть и предоставлял минимальный уровень абстракций для выскоуровнего ЯП, но позволял писать очень эффективный и "близкий к железу" код.



И вот, в 1980 году сотрудник легендарной Bell Labs Бьёрн Страуструп задумался о том, как бы добавить в язык С ОО модель из Simula. Данный проект получил название "C с классами" и был реализован в виде транслятора в обычный С.



Работало это примерно так: в язык были добавлены классы, которые в свою очередь были "калькой" для создания структур определенного типа. Методы класса реализовывались как обычные функции С, которые работали с созданной структурой на основе класса. Но виртуальных методов пока еще не было. А вот наследование классов было изначально.



Уже сейчас мы можем видеть огромное сходство С++ с Simula: Simula добавил ОО в Algol, а C++ добавил ОО в C. Как и в Simula у нас уживается мир объектов и не-объектов (но в уже C++ появились объекты-обертки, но использовать их нужно явно). При этом, способ реализации классов "под капотом" позволял передавать их как по указателю, так и по значению. Да и в целом использование уже обкатанного и эффективного языка С и его инфраструктуры, привело к тому, что новая абстракция практически не имела цены в Runtime.



Язык стремительно стал набирать популярность и уже в 83 Бьёрн Страуструп официально выпустил C++. В язык были добавлены виртуальные методы, перегрузки методов, ссылки (до этого были только указатели из С) и множество других новшеств. ЯП перестал быть "фронтендом" к С, а уже развился в полноценный самостоятельный язык. А в 87 году у него уже появился свой собственный компилятор (G++, является частью GCC).



Более того ЯП активно развивается и по сей день. Каждые несколько лет выходит новый стандарт и новые возможности. Существует несколько независимых крупных компиляторов: GCC, Clang, Microsoft Visual C++.



Окей, давайте разберем ОО модель С++.



Подобно С, С++ позволяет очень тонко настраивать как именно работает ваш код. Например, методы класса по умолчанию являются просто ассоциированными функциями. А значит вы не можете их доопределить в дочернем подклассе или использовать полиморфизм подтипов. Однако, вы можете добавить модификатор virtual к методу и тогда все заработает так, как мы и привыкли. Виртуальные методы не бесплатная абстракция, поэтому С++ дает вам четко определить, где вам это нужно, а где нет.



Чтобы создать объект, ему нужно определить класс. Для создания экземпляра класса используется оператор new. При этом созданный экземпляр будет расположен в куче и передаваться по ссылке. Чтобы очистить память, необходимо использовать оператор delete. И это важное новшество по сравнению с обычным С - у нас появился более высокоуровневый API работы с памятью. Хотя UB и возможность отстрелить себе ногу никуда не делись.