Почитав Б.Страуструпа, Г.Буча и вообще книги об объектно-ориентированном программировании, некоторые приверженцы C делают вывод о том, что C++ - это нечто запредельно сложное и гиганский шаг вперед. Это заблуждение. На самом деле C++ - это тот же C, но с некоторыми удобными упрощениями. Если вы - хороший С-программист и воспринимаете C++ как нечто на порядок более крутое, то это - диагноз. Который называется "перечитал заумных книжек". Это излечимо J
Часто можно слышать споры на тему: писать на C или на C++? При этом существует расхожее мнение о том, что есть два стиля написания программ: стиль С и стиль C++. Они противопоставляются друг другу. C++ ассоциируется с ООП (объектно-ориентированноым программированием), а чистый C - с ПОП (процедурно-ориентированным программированием). ООП и ПОП также противопоставляются.
На самом деле, все, что есть нового в C++ - уже было в C и вы этим пользовались (если действительно много программировали на C). Только в C++ это записывается чуть по-другому. Однажды у меня вышел спор с одним из приверженцев C на эту тему, в результате чего был написан список из 10 различий между двумя языками.
В C++ появились классы и объекты. Технически класс C++ - это тип структуры в C, а объект - переменная такого типа. Разница только в том, что в C++ есть еще модификаторы доступа и полями могут быть не только данные, но и функции (функции-методы).
Функция-метод - это обычная функция C, у которой первый параметр - это указатель на структуру, данные которой она обрабатывает: this. Если сравнить, как выглядят функции-методы в C++ и функции с параметром-указателем на структуру в C, то мы обнаружим, что всего лишь изменилась форма записи. В C++ получается короче, так как this и имя типа во многих случаях писать не обязательно (подразумевается по умолчанию).
Модификаторы доступа - это слова public, private и protected. В C вместо них была внимательность программиста: public - значит с этими полями делаю, что хочу; private - значит к этим полям обращаюсь только с помощью методов этой структуры; protected - то же, что public, но еще можно обращаться из методов унаследованных структур (см. следующий пункт).
То, что в C++ - наследование, в C - это просто структура в структуре. При программировании в стиле C++ применяются такие красивые и звучные слова, как "класс Circle порожден от класса Point" или "класс Point наследуется от класса Circle и является производным от него". На практике все это словоблудие заключается в том, что структура Point - это первое поле структуры Circle.
При этом реальных усовершенствований два. Первое - поля Point считаются так же и полями Circle, в результате доступ к ним записывается короче, чем в C. Второе - в обоих структурах можно иметь функции-методы, у которых имена совпадают с точностью до имени структуры. Например, Point::paint и Circle::paint . Следствие - не надо изобретать имена вроде Point_paint и Circle_paint, как это было в C, а префиксы Point:: и Circle:: в большинстве случаев можно опускать.
В C++ появились две новые операции: new и delete. В первую очередь это - сокращения для распространенных вызовов функций malloc и free:
В стиле C:
В стиле C++:
При вызове new автоматически вызывается конструктор, а при вызове delete - деструктор (см. следующий пункт). Так что нововведение можно описать формулой: new = malloc + конструктор, delete = free + деструктор.
Когда программируешь в стиле C, после того, как завел новую переменную типа структуры, часто надо ее инициализировать и об этом легко забыть. А перед тем как такая структура закончит свое существование, надо ее почистить, если там внутри есть ссылки на какие-то ресурсы. Опять-таки легко забыть.
В C++ появились функции, которые вызываются автоматически после создания переменной структуры (конструкторы) и перед ее уничтожением (деструкторы). Во всех остальных отношениях это - обычные функции, на которые наложен ряд ограничений. Некоторые из этих ограничений ничем не оправданы и мешают: например, конструктор нельзя вызвать напрямую (дестркутор, к счастью, можно). Нельзя вернуть из конструктора или деструктора значение. Что особенно неприятно для конструктора. А деструктору нельзя задать параметры.
Из всех усовершенствований это вызывает наибольшую "щенячью радость". Как обычно, придуманы и звучно-научно-рекламные названия: "полиморфизм", "виртуальный", "абстрактный". Если отбросить разницу в терминологии, то что получим в сухом остатке? А получим мы очередное сокращение записи. И очень большое сокращение.
При программировании на C часто бывает так, что имеется несколько вариантов одной и той же структуры, для которых есть аналогичные функции. Например, есть структура, описывающая точку (Point) и структура, описывающая окружность (Circle). Для них обоих часто приходится выполнять операцию рисования (point). Так что, если у нас есть блок данных, где перемешаны точки, окружности и прочие графические примитивы, то перед нами стоит задача быстро вызвать для каждого из них свою функцию рисования.
Обычное решение - построить таблицу соответствия "вариант структуры - фукция". Затем берется очередной примитив, определяется его тип, и по таблице вызывается нужная функция. В C этот метод применять довольно нудно из-за того, что во-первых, надо строить эту таблицу, а во-вторых, внутри структур заводить поле, сигнализирующее о том, какого она типа, и следить за тем, чтобы это поле содержало правильное значение.
В C++ всем этим занимается компилятор: достаточно обозначить функцию-метод как virtual, и для всех одноименных функций будет создана таблица и поле типа, за которыми следить будет опять-таки компилятор. Вам останется только пользоваться ими: при попыке вызвать функцию с таким именем, будет вызвана одна из серии одноименных функций в зависимости от типа структуры.
Исключение по своей сути - это просто последовательность goto и return. Основан на обычной C-технологии setjmp/longjmp. try и catch - это setjmp с проверкой. throw - это longjmp. Когда вызывается throw, то проверяется: если он окажется внутри блока try, то выполняется goto на парный блок catch. Если нет, то делается return и ищется catch на уровень выше и так далее.
Наличие в throw/catch параметра ничего принципиально не меняет: и в обычном C можно было заполнить какие-то переменные перед вызовом longjmp и потом их проанализировать.
Относитесь к ним как к уродливым функциям и все станет ясно. a + b, где a и b - типа Point это функция от двух аргументов a и b, возвращающая Point:
Написать a+b равносильно вызову такой функции: operator+(a,b). Иногда эта технология удобна, а иногда вносит путаницу.
Многие программисты изучали C на основе языка Pascal. В Pascal есть возможность возвращать из функции больше одного параметра. Для этого применялось магическое слово "var". В C для того, чтобы сделать то же самое, приходилось расставлять в тексте уйму символов "*".
Разработчики C++ вняли стонам несчастных программистов и ввели слово var. А чтобы все это выглядел ооригинально, "var" они переименовали в "&" и назвали "ссылкой". Это вызвало большую путаницу, так как в C уже были понятия "указатель" (та самая звездочка) и "адрес" (обозначался тем же символом &), а понятие "ссылка" звучит тоже как что-то указующе-адресующее. Вот если бы, не мудрствуя лукаво, добавили слово var…
С одной стороны, использование ссылок намного сокращает текст программы. Но есть и неприятности. Во-первых, вызов функции, в которой параметр является ссылкой, выглядит так же, как вызов с обычным параметром. В результате "на глаз" незаметно, что параметр может измениться. А в C это заметно по значку &. Во-вторых, многочисленные звездочки в C напоминают программисту о том, что каждый раз выполняется дополнительная операция * разыменования указателя. Что побуждает сделать разумную оптимизацию. В C++ эти операции остаются незамеченными.
Различие 1. Объекты
Различие 2. Наследование
Различие 3. new и delete
Point *p = (Point*) malloc(sizeof(Point));
free(p);
Point *p = new Point;
delete p;
Различие 4. Конструкторы и деструкторы
Различие 5. Виртуальные функции
Различие 6. Исключения
Различие 7. Перегруженные операторы
Point operator+(Point a, Point b)
Различие 8. Ссылка