В чем преимущество объектно-ориентированного программирования перед процедурным программированием?


77

Я пытаюсь понять разницу между процедурными языками, такими как C, и объектно-ориентированными языками, такими как C ++. Я никогда не использовал C ++, но я обсуждал со своими друзьями, как их различать.

Мне сказали, что C ++ имеет объектно-ориентированные концепции, а также публичные и частные режимы для определения переменных: вещей, которых нет в C. Мне никогда не приходилось использовать их при разработке программ на Visual Basic.NET: каковы их преимущества?

Мне также сказали, что если переменная общедоступна, к ней можно получить доступ где угодно, но неясно, чем она отличается от глобальной переменной в языке, подобном C. Также неясно, чем частная переменная отличается от локальной переменной.

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

if ( login == "admin") {
    // invoke the function
}

Почему это не идеально?

Учитывая, что, кажется, существует процедурный способ сделать все объектно-ориентированным, почему я должен заботиться об объектно-ориентированном программировании?




26
+1, чтобы противостоять некоторым отрицательным голосам. Если бы коллега задал мне такой вопрос, у меня, вероятно, были бы некоторые опасения, и я мог бы даже понизить его мнение (предполагая, что рядом с ним была какая-либо стрелка вниз). Тем не менее, этот вопрос, похоже, задается будущим инженером-программистом, и похоже, он потратил некоторое время на обдумывание и обсуждение этой темы перед публикацией. Я голосую за то, что помог ему, а не уволил.
ДХМ

14
@DXM Отличная идея! Стрелки вниз / вверх, плавающие вокруг коллег ... Это будет творить чудеса.
Яннис

2
Стандартный встречный аргумент: есть также ассемблерный способ сделать все, что вы можете делать в C, так почему вы должны заботиться о C? (Подсказка: все дело в повышении уровня абстракции. С ++ удается это сделать, не жертвуя большей частью скорости С. ИМО - главная причина успеха С ++.)
sbi

Ответы:


135

Все ответы до сих пор были сфокусированы на теме вашего вопроса, как было сказано, а именно: «В чем разница между c и c ++». На самом деле, звучит так, будто вы знаете, в чем разница, вы просто не понимаете, зачем вам эта разница. Итак, другие ответы пытались объяснить ОО и инкапсуляцию.

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

Вы не понимаете цели C ++ или OO, потому что вам кажется, что вашему приложению просто необходимо хранить данные. Эти данные хранятся в переменных. «Почему я хочу сделать переменную недоступной? Теперь я больше не могу получить к ней доступ. Делая все общедоступным, или, что еще лучше, глобальным, я могу читать данные из любого места, и проблем нет». - И вы правы, исходя из масштаба проектов, которые вы сейчас пишете, вероятно, проблем не так много (или есть, но вы просто о них еще не узнали).

Я думаю, что основной вопрос, на который вы действительно должны ответить, это: «Зачем мне когда-либо хотеть скрывать данные? Если я это сделаю, я не смогу с этим работать!» И вот почему:

Допустим, вы начинаете новый проект, открываете текстовый редактор и начинаете писать функции. Каждый раз, когда вам нужно что-то сохранить (чтобы запомнить это позже), вы создаете переменную. Чтобы упростить ситуацию, вы сделаете свои переменные глобальными. Ваша первая версия вашего приложения работает отлично. Теперь вы начинаете добавлять больше функций. У вас есть больше функций, определенные данные, из которых вы хранили ранее, должны быть прочитаны из вашего нового кода. Другие переменные должны быть изменены. Вы продолжаете писать больше функций. Что вы, возможно, заметили (или, если нет, вы обязательно заметите в будущем), так как по мере того, как ваш код становится больше, вам потребуется все больше и больше времени, чтобы добавить следующую функцию. И по мере того, как ваш код становится больше, становится все труднее добавлять функции, не нарушая того, что раньше работало. Почему? Потому что вам нужно помнить, что всеваши глобальные переменные хранятся, и вы должны помнить, где все они изменяются. И вам нужно помнить, какую функцию можно вызывать в каком именно порядке, и если вы вызываете их в другом порядке, вы можете получить ошибки, потому что ваши глобальные переменные еще не совсем корректны. Вы когда-нибудь сталкивались с этим?

Насколько велики ваши типичные проекты (строки кода)? Теперь представьте проект в 5000 - 50000 раз больше вашего. Кроме того, в нем работают несколько человек. Как все в команде могут помнить (или даже знать), что делают все эти переменные?

То, что я описал выше, является примером идеально связанного кода. И с незапамятных времен (при условии, что время началось 1 января 1970 года), человеческий род искал способы избежать этих проблем. Чтобы избежать их, нужно разделить код на системы, подсистемы и компоненты и ограничить количество функций, имеющих доступ к любому фрагменту данных. Если бы у меня было 5 целых чисел и строка, представляющая какое-то состояние, мне было бы легче работать с этим состоянием, если бы только 5 функций устанавливали / получали значения? или если 100 функций устанавливают / получают те же значения? Даже без ОО-языков (например, C) люди усердно работали над изоляцией данных от других данных и созданием четких границ разделения между различными частями кода. Когда проект достигает определенного размера, простота программирования становится невозможной, «могу ли я получить доступ к переменной X из функции Y»,

Вот почему концепции ОО были введены, и именно поэтому они такие мощные. Они позволяют вам скрывать свои данные от себя, и вы хотите делать это специально, потому что чем меньше кода, который видит эти данные, тем меньше вероятность того, что при добавлении следующей функции вы что-то сломаете. Это основная цель концепций инкапсуляции и ОО-программирования. Они позволяют вам разбивать наши системы / подсистемы на еще более детализированные блоки до такой степени, что, независимо от того, насколько велик весь проект, к данному набору переменных можно получить доступ только через 50-200 строк кода, и все! Очевидно, что ОО-программирование гораздо больше, но, по сути, именно поэтому C ++ дает вам возможность объявлять данные / функции как частные, защищенные или общедоступные.

Второй величайшей идеей в ОО является концепция уровней абстракции. Хотя процедурные языки также могут иметь абстракции, в C программист должен сознательно приложить усилия для создания таких слоев, но в C ++, когда вы объявляете класс, вы автоматически создаете слой абстракции (это зависит от вас, является ли эта абстракция или нет добавит или удалит значение). Вы должны прочитать / исследовать больше об уровнях абстракции, и если у вас есть больше вопросов, я уверен, что этот форум будет более чем рад ответить на них.


5
Отличный ответ, похоже, достиг соответствующего уровня с учетом вопроса
Карлос

29
+1 ... в основном для строки "И с
незапамятных

4
@Chad - я рассчитывал, что одна эта линия должна набрать мне хотя бы одно очко :)
ДХМ

Есть способ решить проблему масштаба, о которой вы говорите в процедурной парадигме. Это называется функции. Но хороший способ объяснить проблему.
annoying_squid

@DXM - я не уверен, правильно ли я понял ответ. Мы можем достичь той же функциональности set / get и в процедурном программировании. Мы можем написать функции set / get в C для изменения / получения глобальной переменной. Используя этот метод также, мы ограничиваем количество функций, которые изменяют глобальные переменные. И даже в ООП, если мы также используем методы set / get, мы будем использовать эти методы извне объекта для изменения значений.
кадина

10

Хм ... может быть, лучше сделать резервную копию и попытаться дать некоторое представление об основных целях объектно-ориентированного программирования. Большая часть цели объектно-ориентированного программирования состоит в том, чтобы позволить создание абстрактных типов данных. Для действительно простого примера, с которым вы, несомненно, знакомы, рассмотрим строку. Строка, как правило, имеет буфер для хранения содержимого строки, некоторые функции, которые могут работать со строкой (поиск в ней, доступ к ее частям, создание подстрок и т. Д.). Кроме того, будет (по крайней мере, как правило) что-то отслеживать (текущую) длину строки и (возможно) размер буфера, поэтому, если (например) вы увеличите размер строки с 1 до 1000000, он будет знать, когда ему потребуется больше памяти для хранения большего содержание.

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

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

Что касается безопасности, я бы отметил, что хотя это разумно по аналогии, это не так, как на самом деле работают. В частности, доступ в C ++ специально не предназначен для удовлетворения тех же требований, что и доступ в операционной системе. Операционная система должна обеспечивать соблюдение ограничений , так что (например) обычный пользователь не может сделать что - то , отведенные для администратора. В отличие от этого, контроль доступа в C ++ предназначен только для предотвращения несчастных случаев., Любой, кто хочет, может легко обойти их. Они находятся в том же порядке, что и отметка файла только для чтения, чтобы вы случайно не удалили его. Если вы решите удалить файл, тривиально изменить его с чтения только на чтение и запись; все, что нужно сделать только для чтения, - это заставить вас хотя бы подумать об этом и принять решение об удалении файла, чтобы он не был удален случайно из-за неправильного нажатия неправильного ключа.


6

ООП против С не совсем о том, что вы обсуждали. Это прежде всего упаковка кода в области, которые не будут / не могут непреднамеренно (или иногда даже намеренно) влиять друг на друга.

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


4
-1. В C нет ничего исключительного, что делает все функции глобальными. Вы можете объявить любую функцию статической и тем самым ограничить ее область действия локальным файлом. C не отличается от C ++, Java и т. Д. В этом аспекте. Кроме того, ООП не относится к языковому синтаксису, вы можете писать ОО-программы на C просто отлично, хотя они будут немного более грубыми, чем в языках с поддержкой синтаксиса для ОО. И наоборот: вы не получаете ООП только потому, что выбрали язык, который поддерживает ООП. Объектная ориентация - это стиль программирования , а не языковая особенность.

@Lundin: Хотя вы технически правы, вы упустили момент. Языки ООП устанавливают поведение по умолчанию для поведения ООП. С не делает.
Джон Фишер

1
В ОО-языках нет ничего, что заставляло бы вас делать это. Например, я видел бесчисленное количество непонятных программ на C ++ без каких-либо упоминаний. Точно так же, если у вас нет понятия об ОО, но вы пытаетесь реализовать классы, наследие и т. Д., Есть вероятность 100% создать испорченную программу.

@Lundin: я не думаю, что C ++ - хороший пример. Он (или, по крайней мере, был) предназначен для возможности компилировать программы на Си без (значительной) модификации. Добавление классов сверху не делает его языком ООП на уровне C # или Java, но оно позволяет осуществлять такого рода разработку.
Джон Фишер

Вы также можете писать не-OO-программы на Java, просто взломав один большой основной файл ... OO по- прежнему не зависит от языка, если программист не знает об OO, ни один язык в мире не спасет их.

4

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

Одним моментом, который не обсуждался подробно, является аспект интерфейса / реализации. Интерфейс описывает поведение, но не реализацию. Таким образом, интерфейс списка описывает концепциюсписка и его поведение: можно ожидать такие вещи, как методы добавления, удаления и размера. Теперь существует много разных способов реализации этого списка, например, в виде связанного списка или использования буфера массива. Сила ОО-программирования заключается в том, что с помощью интерфейса вы можете рассуждать о поведении, не зная о реализации. Доступ к внутренним переменным или методам разрушил бы эту абстракцию, вы не могли бы заменить одну реализацию списка другой, и вы не могли бы улучшить существующую реализацию, не касаясь кода, использующего класс. Это одна из основных причин, по которой нужны закрытые переменные и методы: для защиты внутренних деталей реализации, чтобы абстракция оставалась неизменной.

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


Концепция интерфейсов не уникальна для объектно-ориентированных языков. Более важным фактором, я думаю, является то, что в не-ООП языках почти все функции, используемые в модуле, должны принадлежать одному и тому же глобальному пространству имен. Для этого необходимо, чтобы имена функций были либо префиксными, чтобы указывать, на что они действуют, либо иметь множество методов с похожим звучанием, которые делают совершенно разные вещи (например, SetLocationмогут использоваться для перемещения a Monster, в то время как SetPositionмогут перемещаться a PopupWindow, и Moveмогут использоваться для регулировки положения. а DisplayCursor). Пытаясь найти правильный метод "переместить" ...
суперкат

... можно сделать намного проще, если при написании MyMonstor->редактора отображается только список методов, применимых к вещам типа Monster. Если существует множество различных типов вещей, каждая из которых поддерживает около дюжины операций, сокращение количества беспорядка в списках методов на 90% может значительно снизить производительность.
суперкат

Конфликт имени @supercat - это проблема языка, а не проблема ООП. С другой стороны, пространства имен проблематичны, потому что компилятору по существу необходимо автоматически переименовать функцию или изменить ее. Так почему бы просто не сделать это вручную?
annoying_squid

@annoying_squid: ООП предоставляет возможность эффективно использовать тип первичного аргумента функции для выбора пространства имен. Если у меня есть переменная itтипа SuperFancyWhizBang, вызов одного из SuperFancyWhizBangметодов itне требует выписывания типа SuperFancyWhizBang; Поговорка it.woozle()заставит компилятор автоматически искать woozleвнутри SuperFancyWhizBang.
суперкат

3

Существует способ сделать все с помощью машины Тьюринга или, по крайней мере, на языке ассемблера для машинного кода, который в конечном итоге будет компилироваться программой на C или C ++.

Таким образом, разница не в том, что может делать код, а в том, что могут делать люди.

Люди делают ошибки. Много.

ООП вводит парадигму и синтаксис, которые помогают уменьшить размер и плотность вероятности пространства возможных ошибок человеческого кодирования. Иногда, делая ошибку недопустимой для определенного класса объекта данных (например, это не метод, объявленный для этого объекта). Иногда, делая ошибку более многословной или стилистически странной по сравнению с каноническим использованием языка. Иногда требуется интерфейс с гораздо менее вероятным непоследовательным или запутанным использованием (публичный или частный). и т.п.

Чем больше проект, тем выше вероятность ошибок. Какой новый кодер мог бы не подвергаться воздействию, если бы только испытывал небольшие программы. Таким образом, потенциальная загадка, почему ООП ценно.


2

Ваш вопрос кажется больше о цели ООП, а не о разнице. Концепция в вашем посте - Инкапсуляция; и существует инкапсуляция для поддержки CHANGE. Когда другие классы получают доступ к вашим внутренним объектам, становится трудно изменить их, не нарушая их. В ООП вы предоставляете интерфейс (открытые члены), через который вы позволяете другим классам взаимодействовать с вашими, и вы скрываете свои внутренние компоненты, чтобы их можно было безопасно менять.


Просто используйте прототипы функций. Это инкапсуляция.
annoying_squid

2

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

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


1

Как говорили многие, любая программа, однажды скомпилированная, превращается в двоичный код и, поскольку двоичная строка может использоваться для представления целого числа, любая программа в конечном итоге представляет собой просто число. Однако определить нужное вам число может быть довольно сложно, и именно поэтому появились языки программирования высокого уровня. Языки программирования - это всего лишь модели кода сборки, который они в конечном итоге создают. Я хотел бы объяснить вам разницу между процедурным и ОО-программированием с помощью этой очень хорошей статьи о контекстно-ориентированном программировании http://www.jot.fm/issues/issue_2008_03/article4/

как вы можете видеть из этой картины, изображенной в статье, процедурное программирование предоставляет только одно измерение, чтобы связать вычислительную единицу с именем. Здесь вызовы процедур или имена напрямую отображаются в реализации процедур. На рисунке вызов m1 не оставляет выбора, кроме вызова единственной реализации процедуры m1.

Объектно-ориентированное программирование добавляет другое измерение для разрешения имен к процедурному программированию. В дополнение к имени метода или процедуры при отправке сообщения учитывается получатель сообщения при поиске метода. На рисунке b мы видим две реализации метода m1. Выбор соответствующего метода зависит не только от имени сообщения m1, но и от получателя фактического сообщения, здесь Ry.

Это действительно позволяет инкапсуляцию и модульность.

введите описание изображения здесь

Рисунок-c, наконец, о предметно-ориентированном программировании расширяет объектно-ориентированную методику диспетчеризации еще одним измерением.

Надеюсь, что это помогло вам думать о ООП с другой точки зрения.


0

(+1) Задавать вопрос о чем-то, чего ты не понимаешь, это хорошо, даже если это звучит глупо.

Разница заключается в объектно-ориентированном программировании. «Простой C», работает с данными и функциями. «C ++» добавляет понятия «объект и классы», а также несколько связанных вторичных понятий.

Тем не менее, я призываю разработчиков изучать "Простой C" перед "C ++". Или «Процедурный Паскаль» перед «Объектным Паскалем».

Многие разработчики считают, что студенты должны учить только одному.

Например, старые учителя, которые не получают ОО, а преподают только «Простой структурированный С».

Или «хипстерские» учителя, которые преподают только ОО, но не «Простой С», потому что «вам это не нужно». Или оба, не заботясь о порядке преподавания.

Я скорее думаю, что студенты должны обучаться как «Структурированная равнина C», так и «Объектно-ориентированный C (C ++)». С «Plain C», сначала, и «C ++», позже.

В реальном мире вам нужно выучить обе парадигмы (плюс другие парадигмы, например, «функциональные»).

Мышление структурированных программ как большого, одноэлементного «объекта» может помочь.

Вы также должны сделать акцент на пространствах имен («модулях»), на обоих языках многие учителя просто игнорируют это, но это важно.


Пространства имен и перегрузки только усложняют понимание программы. Это делает процесс идентификации контекстно-зависимым. Когда вы видите foo()в C ++, это может быть глобальная функция, функция в текущем пространстве имен, функция в пространстве имен, с которой вы используете using, метод, унаследованный метод, и если он находится в вызове функции: он может находиться в пространстве имен, которое может быть решен путем поиска имени на основе аргументов, и подобное верно для Java и C #. В C это может быть только статическая функция в текущем исходном файле или функция из заголовка.
Кальмарий

Написание MODULE_Foo () везде может быть визуальным беспорядком, но, по крайней мере, вы точно знаете, какая это функция.
Кальмарий

Решение @Calmarius, очевидно, состоит в том, чтобы не называть ничего фу .

0

Одним словом, управление проектами. Я имею в виду, что C ++ помогает мне применять правила того, как мой код используется другими. Работая над проектом с 5,5 миллионами строк, я считаю, что объектно-ориентированное программирование очень полезно. Еще одним преимуществом является компилятор, который заставляет меня (и всех остальных) следовать определенным правилам и ловить мелкие ошибки во время компиляции. Также есть все теоретические преимущества, но я просто хотел сосредоточиться на повседневных практических вещах. Ведь все это компилируется в машинный код.


-1

Объектно-ориентированное программирование - это процедурное программирование с блоками.

В PP у вас есть один блок, одно состояние, которое становится невероятно большим по мере роста проекта, вызывая побочные эффекты каждый раз, когда вы забываете о крошечном кусочке этого большого состояния.

В ОО у вас много ящиков, много состояний, и по мере роста проекта ящики немного растут, а количество ящиков значительно увеличивается.

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

В функциональном программировании у вас есть много функциональных блоков, и вы решаете, что каждая функция имеет одну запись (параметры) и один выход (возврат), без какого-либо другого доступа к внешнему контексту.

Поскольку нет состояния и нет побочных эффектов (по замыслу), вы можете безопасно анализировать любую функцию отдельно от целого и знать на 100%, как она будет вести себя при любых обстоятельствах.

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

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

Это также значительно превзойдет PP, потому что вы можете расширять проект гораздо дольше, так как больше нет состояния XXXXXXXL, которое нужно отслеживать.

Таким образом, PP, вероятно, самый простой способ подойти к простой программе, а FP, вероятно, самый простой способ подойти к сложной.

Если вы учитываете цель объединения всех кодовых баз и улучшения повторного использования кода, всегда следует использовать FP, поскольку это единственная парадигма, имеющая смысл в очень большом масштабе, а также единственная парадигма, которая имеет возможность повторного использования на 100% (вы можете просто скопируйте, вставьте функцию и используйте ее где-нибудь еще, без каких-либо накладных расходов).

И вы получаете 100% надежное модульное тестирование бесплатно.

И вам не нужно писать «приватный статический финал of_doom genius awesome string_1».

И вы получаете параллелизм бесплатно.


-3

Простое различие в одном предложении состоит в том, что C ++ - это C с классами (хотя теперь это намного больше). Я не понимаю, почему вы не хотите изучать различия между двумя, читая отличную статью о C ++ в Википедии .... .Эта статья очень вам поможет: - C ++ (Википедия)

Также поможет поиск по этому вопросу. Просить случайных людей объяснить это может быть сложно. ИМХО, читая лучше, чем спрашивая


Я прочитал их, но они просто сказали, где они используются, но до сих пор не решили мой вопрос.
Нико

Я не задавал вопрос, не прикладывая усилий, я погуглил, но все еще не мог понять разницу, поэтому я встретился со stackoverflow, чтобы помочь мне с этим
Нико

1
@niko, вы меня не так поняли. Я имел в виду, что вы должны попытаться понять разницу между ними, прочитав. Запрашивать у ваших друзей нехорошо. Потому что они обеспечат свое собственное понимание, которое может вас не удовлетворить. Но, не волнуйтесь, здесь есть отличные сверстники, они наверняка вам помогут :-)
Pankaj Upadhyay

2
Я не понизил голос, но был очень искушен в "C ++ - это C с классами". Те из нас, кто действительно умеет делать C ++, отрабатывают свои задницы, пытаясь выкинуть это из головы людей.
DeadMG

1
@Pankaj: Это верно. Это был C с классами. Это определенно больше не C с классами, и называть его таковым почти 30 лет. C ++ прошел очень долгий путь с тех пор. Люди, которые сейчас пишут код на C ++, никогда не обращаются к нему таким образом. Это поощряет худшие привычки и неправильное впечатление.
DeadMG
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.