На самом деле, не такой он и плохой. Хороший даже, вон сколько всего понаписали. Сидят такие русские и украинские Рсдновцы и пишут, пишут. Шаблоны всякие используют, бусты с стлпортами, всяческие хитрые менеджеры памяти придумывают. Люди книжки пишут, ну типа "10001 совет, как не свернуть себе шею, пытаясь использовать StlPort 4.6.2 в EVC 3.0.". Деньги зарабатывают.
Только обычных программистов больше. Индусы, китайцы, японцы, русские и простые американцы — и им нужно не сублимировать ночами, изучая премудрости языка, а работу делать. И уйти с работы ранним вечером, потому что дома — жена и дети, и только в России 30 лет для программиста — это уже почти пенсия, а то как же он женатый будет 80 часов в неделю за компом сидеть.
Конкретно, в языке С++ есть недостатки. Эти недостатки известны, и к счастью, несмотря на ярых консерваторов на Рсдне, разработчики языка эти недостатки рано или поздно исправят, так как похоже до них доходит, что таки надо. А еще есть фирма MS, которая в C++/CLI уже много исправила
Но вы, господин d Bratik, много чего "веселого" написали.
Хотя по поводу времени компиляции согласен.
Это смешно, требовать использовать какие-то идиомы от 10 инусских выпускников университета города Columbus, OH. Они вам еще ВСЕ имеющиеся хедеры в CPP включат. Чего уж там, если ваш американский коллела, не зная как получить из указателя на базовый класс его наследника, запихивает функции и переменные в базовый класс, хотя имеют они смысл толкьо для наследника. И то все фигня, а когда сидящий через 3 метра наш родной русский программер делает на следующий день тоже самое, уже ни о каких идиомах речь не идет! А еще есть соседняя комната, код из которой вы иногда видите и даже портируете. Хе-хе.
Отсутствие finally — довольно дурацкая шутка создателей языка.
К сожалению, я последние 4 года не пишу с исключениями, так как в компиляторе нет для них поддержки (осталось еще год продержаться, дальше мы депрекейтим эту платформу), но finally я в свое время использовал в OPascal, и знаю, насколько это удобно. Конечно, все можно эмулировать, но только если finally код сокращает, то эмуляция — наоборот увеличивает, а уж понятности точно не добавляет.
Все остальное, конечно критики не выдерживает. Особенно отсутствие встроенной проверки при работе с указателями (ну типа массивами).
Господа, а еще в языке С++ есть не толлько недостатки, но и проблемы. Каждый раз, когда у вас возникает проблема в программе, которая была вызвана тем, что вы неправильно изложили свои мысли на языке и компилятор не ругнулся, это демонстрация этих проблем.
Когда нибудь приводили void* к указателю на один из базовых классов в множественном наследовании? А в массиве срезанные класы хранили? А пытались понять, почему вы не можете вызвать метод базового класса с одним типом параметра, когда вы написали перегрузку, а не переопределение? А пытались понять, почему функция map::erase в VC++ возвращает итератор, а в StlPort — void?
А еще есть странности реализации. Например, при портирвании dsp в vcproj в послденем wchar остается как unsigned short, а в новых проектах как честный тип. И фиг оно слинкуется! И когда вы найдете отличия в експотрах и импортах в бинарных файлах, фиг вы еще поймете, как это поправит.
Много можно говорить, но дело все в том, что
Язык С++ — для того, чтобы решать проблемы язка, а нормальный язык должен быть создан для того чтобы решать проблемы предметной области.
И если вам и мне интересно заниматься этим, то нашим работодателям — нет.
Re[10]: Почему настоящие программисты избегают C++
MN>>Да согласен — ваша правда... это я поторопился... но как-то у меня такой проблемы никогда не было... наверное потому, что для работы с контейнерами C++ всегда использовал итераторы, а для доступа к массивам в стиле pure C использовал знаковый int и никогда не путал эти понятия между собой, чего и вам советую... ну или если вы моему совету не внемлите, то обращайтесь к С. Ю. Губанову — он вам других советов надаёт
N>для любителей signed int'ов:
N>положим захотелось нам искать среднее двух чисел и написали мы функцию: N>int kaka (int a, int b){return (a+b)/2;}
N>и всё вроде тип-топ, но вот тут сунули нам два числа (вполне корректных):
N>int a = 2113929216; N>int b = 2113929210;
N>и что? а какое решение-то простое есть? ассемблер в три команды не предлогать, всё на с++ N>p.s. я решение знаю, но не сказал бы что оно простое
Ну зачем же ставить заведомо нерешаемые задачи?
Над такими лучшие умы человечества бьются не один десяток лет, а Вы хотите чтоб Вам на каком-то инетрнет-форуме всё разрулили.
Re[10]: Почему настоящие программисты избегают C++
Здравствуйте, nixite, Вы писали:
N>для любителей signed int'ов:
N>положим захотелось нам искать среднее двух чисел и написали мы функцию: N>int kaka (int a, int b){return (a+b)/2;}
N>и всё вроде тип-топ, но вот тут сунули нам два числа (вполне корректных):
N>int a = 2113929216; N>int b = 2113929210;
N>и что? а какое решение-то простое есть? ассемблер в три команды не предлогать, всё на с++ N>p.s. я решение знаю, но не сказал бы что оно простое
Проблема переполнения остаётся и при использовании беззнаковых целых. А для int в данном случае решение есть и простое (не сказал бы что красивое, но...). Приводим a и b к long long, а после деления обратно к int.
Пример (Windows):
#include"stdafx.h"using namespace std;
int Aver(int a, int b);
int _tmain(int argc, _TCHAR* argv[])
{
int a = 0, b = 0;
cout << "a? ";
cin >> a;
cout << "b? ";
cin >> b;
cout << "(" << a << " + " << b << ") / 2 = " << Aver(a,b) << endl;
return 0;
}
int Aver(int a, int b)
{
return static_cast<int>((static_cast<long long>(a) + static_cast<long long>(b))/2);
}
ИМХО, твой пример со средним арифметическим неудачный. Что же касается знаковых индексов в векторе, то они нецелесообразны по двум причинам:
1. дополнительная ошибочная ситуация с отрицательным индексом
2. размер массива уменьшается в два раза (по сравнение с таким же знаковым типом)
Любая сложная технология неотличима от волшебства. (Артур Кларк)
Re[11]: Почему настоящие программисты избегают C++
Здравствуйте, d Bratik, Вы писали: N>>для любителей signed int'ов:
N>>положим захотелось нам искать среднее двух чисел и написали мы функцию: N>>int kaka (int a, int b){return (a+b)/2;}
N>>и всё вроде тип-топ, но вот тут сунули нам два числа (вполне корректных):
N>>int a = 2113929216; N>>int b = 2113929210;
N>>и что? а какое решение-то простое есть? ассемблер в три команды не предлогать, всё на с++ N>>p.s. я решение знаю, но не сказал бы что оно простое
DB>Решение состоит в том, что система должна генерировать исключение (exception) при переполнении. Отсутствие этой возможности я забыл добавить в качестве 7-го пункта в списке ошибок проектирования языка.
Функции, логика которых не предусматривает ошибочных ситуаций, не должны кидать исключений. А функция вычисления среднего арифметического относится как раз к таким. Т.е. предложенное тобой решение с генерацией исключения неверно.
Любая сложная технология неотличима от волшебства. (Артур Кларк)
Здравствуйте, d Bratik, Вы писали:
DB>...настоящие программисты избегают C++
И предпочитают делфи где-то по следующим причинам:
1. За то что наследование используемых модулей не поддерживается.
Т.е. Если модуль А использует Модуль Б, и оба они используют модуль С,
то недостаточно прописать использование модуля с в Б, нужно это
использование обязательно и в А прописать.
2. За отсутствие шаблонов.
3. За отсутствие возможности создания автоматических объектов (все объекты изначально является указателем).
Соответственно приходистя вручную вызывать конструктор/деструктор (для чего и TRY..Finnaly)
4. За отсутствие множественного наследования
5. За отсутствие возможности перегрузки операций
6. За WITH благодаря которому код становится не читабельным до ужаса...
7. За дикую абстрактность от GUI модели, благодаря чему некоторые события не доступны,
некоторые не работают, а про главное окно приложения которое делит функционал с окном
Application я просто молчу. Хорошим примером поведения этой абстракности является функция MsgBox.
Можно ради интереса проследить что она делает (сколько вложенных вызовов). А еще класно
реализован Handle у компонентов — просто бестселлер, понял когда случайно вызвал в
деструкторе.
8. За жесткие ограничения на место описания переменных функции — между названием функции и началом блока
9. За невозможность смешивания переменных и функций класса при описании (вначале переменные а затем функции и не иначе)
10. За отсутвие удобных операторов типа +=, *=, -= и т.д. Про ++i и i++ я просто молчу.
11. За явное приведение типов. Особенно сильно "ЛЮБЯТ" за вызов функции Trunc для приведения вещественного в целому.
12. За отсутствие менеджера конфигураций. Так чтобы сделать Debug и Release хотябы, и пользоваться просто переключая их.
13. За дикий размер EXE, если конечно же не юзать пакаджи.
14. За то что ошибочная работа встроенных функций ведет к генерированию исключения, а не возврату кода ошибки. При этом во многих случаях приходится писать просто try ... except end; чтобы пропустить эту фичу.
15. За то что она не MDI. Это ужасно "УДОБНО". Приходится очищать рабочий стол перед открытием делфи, да и две запущенные — это головняк ("КРУТО"), поскольку никогда не знаешь в редакторе какой находишся. Иногда по ALT-TAB переключается только редактор, а главное окно нет.
16. За WITH благодаря которому дебаггер не показывае значение переменных типа with TComeCObject.Create(...) do Visible := TRUE;
Значение Visible — не увидишь никогда. Только если with SomeObject do SomeProperty := SomeValue; то в ТОЛЬКО окне свойств надо подставить SomeObject.SomeProperty и только тогда будет значение
17. За дебаггер который видит стек вызовов исключительно ограниченный модулями, пути которых включены в проект.
Так если в проект не подключить путь для просмотра (Project\Options\Search Path) C:\Program Files\Borland\Delphi6\Source\Vcl;C:\Program Files\Borland\Delphi6\Source\Rtl;C:\Program Files\Borland\Delphi6\Source\Rtl\Common;C:\Program Files\Borland\Delphi6\Source\Rtl\Sys;C:\Program Files\Borland\Delphi6\Source\Rtl\Win
то при возникновении события OnEnter у компонента на форме можно увидеть стек вызовов только с этой функцией.
НО!!!!!!!!!!!!! Если подключить пути то будет КУЧА!!!!!!! варнингов для делфевых модулей при компиляции, за которыми и "своих" не видно.
18. За отсутствие оператора "?". Есть только два псевдоаналога — варианты функции ifthen. При этом нормально работать можно со строкой и Integer-подобными значениями.
Когда речь идет об объекта то тогда запись выростает до TType(ifthen(...,Integer(Object1),(object2)) — грустно...
19. За компилятор, который хавает на ура запятую без указания последнего необязательного параметра функции.
Т.е. если function f(p1: Integer; b1: Boolean=false; B2: Boolean = false), то такое прокатит на ура — f(1,false,);
20. За директивы компилятора сделанные в стиле коментариев и мещающие коментированию текста их содержащего
21. За отсутствие нормального хелпа к системным функциям. Для того чтобы определить где находится описание сетевой
функции нужно выполнять поиск по каталогу сырцов. К примеру NetWkstaGetInfo которая вообще отсутствиет в
стандартных сырцах Ламерская система....
22. За то что значения дефолтовых параметров надо описывать и в описании функции/метода и в их реализации
23. За то что нельзя создать два пакета содержащие модули с одинаковыми названиями — среда не позволит, будет каждый раз ругаться что Пакет ХХХ использует модуль УУУ, который уже содержится в ХХ1 — это очень удобно, в с++ такого не добиться
24. За то что иногда невозможно открыть справку по F1, если модуль содержит ошибки.
Ну и как бы P.S.:
Все эти любимости собраны в 6-й версии делфи, поэтому если у кого одна из этих ужасно любимых фич не пойдет на другой версии — не расстраивайтей, всегдя найдется что полюбить в замен, на то это и делфи!
Ну и как бы P.P.S.:
Нисколько не хотел никого задеть кто пишет проги на делфи — у каждого свой вкус, ну и разные задачи требуют разных инструментов.
Re[10]: Почему настоящие программисты избегают C++
MN>>Да согласен — ваша правда... это я поторопился... но как-то у меня такой проблемы никогда не было... наверное потому, что для работы с контейнерами C++ всегда использовал итераторы, а для доступа к массивам в стиле pure C использовал знаковый int и никогда не путал эти понятия между собой, чего и вам советую... ну или если вы моему совету не внемлите, то обращайтесь к С. Ю. Губанову — он вам других советов надаёт
N>для любителей signed int'ов:
N>положим захотелось нам искать среднее двух чисел и написали мы функцию: N>int kaka (int a, int b){return (a+b)/2;}
N>и всё вроде тип-топ, но вот тут сунули нам два числа (вполне корректных):
N>int a = 2113929216; N>int b = 2113929210;
N>и что? а какое решение-то простое есть? ассемблер в три команды не предлогать, всё на с++ N>p.s. я решение знаю, но не сказал бы что оно простое
int kakashka( int a, int b )
{
return (a>>1 + b>>1) + ( ((a&1)&&(b&1))?1:0 );
}
Здравствуйте, nixite, Вы писали:
N>для любителей signed int'ов:
N>положим захотелось нам искать среднее двух чисел и написали мы функцию: N>int kaka (int a, int b){return (a+b)/2;}
Братику:
Во-первых, про исключения при переполнении. А не пофиг ли, что будет исключение? Ведь факт переполнения можно выявить и другим способом, но от факта нам ни горячо, ни холодно. Нам нужна корректная обработка, чтобы результат был, а не отлуп на удивление пользователю.
Вариант ответа:
int mid(int a, int b)
{
return a/2 + b/2 + (a%2 + b%2)/2;
}
Здравствуйте, d Bratik, Вы писали:
DB>Здравствуйте, _Obelisk_, Вы писали:
DB>>>Вы наверное писали очень небольшие программы, без GUI. Для создания программ С++ подходит, но для создания систем — нет.
_O_>>Отнюдь. Я, к примеру, один из разработчиков вот этого : http://www.telelogic.com/products/tau/developer/index.cfm. (список поддерживаемых фич тут _O_>>http://www.telelogic.com/products/tau/developer/features.cfm). Продукт, включая GUI, полностью написан на С++. Работает под Win, Linux, Solaris.
DB>Сайт выглядит очень профессионально. Интересно было бы взглянуть на внешний вид самой программы, а также узнать, на чем она написана (Qt?), и поддерживает ли она расширение своей функциональности на каком-нибудь языке программирования.
Обелиск, мои поздравления!
(Хотя лично у меня к UML Suite, кажется, 1999 года — очень большие претензии. Впрочем, тут могла быть обоюдная кривизна рук).
DB>std::vector<int> v;
DB>// Следующий код работает бесконечно, поскольку (size_type)(-1) == 4 млрд.
DB>for (std::vector<int>::size_type i = 0; v.size() - 1; ++i)
DB>{
DB> ...
DB>}
DB>
Что-то я никак не въеду в смысл операции "v.size() — 1". Даже если это будет int, то, например, со зрачением "v.size() = 2" мы получаем проход по памяти, так как "v.size() — 1 == 1".
Проблемы с беззнаковыми целыми и отсуствием контроля переолнения конечно есть. Но пример не к черту.
ЗЫ
Ты не перечислил и 10 процентов граблей.
И вообще ты не понял тонкую душу Страуструпа. Он изобретал язык который позволил бы постоянно тренировать мозг и нервы.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, SWW, Вы писали:
SWW>Кхм, интересно... Человек приводит заведомо неправильный код и говорит: С++ плохой язык потому что на нем можно написать неправильную программу — вот, видите, я же смог!
SWW>А если бы v.size() было знаковым, разве этот код работал бы?
Я так понимаю остальные замечания возражений не вызвали.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, d Bratik, Вы писали:
DB>Сударь, код совершенно коректный: "для всех элементов кроме последнего". В случае пустого вектора код работает бесконечно. Для демонстрации проблемы можно было бы завернуть цикл от последнего элемента до первого:
DB>
DB>std::vector<int> v;
DB>for (std::vector<int>::size_type i = v.size() - 1; i >= 0; ++i)
DB>{
DB> ...
DB>}
DB>
Вот это пример хороший.
SWW>>А если бы v.size() было знаковым, разве этот код работал бы?
DB>Да, причем совершенно корректно.
Нет, уж. Он работал бы только при орпеделенном содержимом тела цикла (если там удалять элементы).
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[11]: Почему настоящие программисты избегают C++
Здравствуйте, d Bratik, Вы писали:
DB>Решение состоит в том, что система должна генерировать исключение (exception) при переполнении. Отсутствие этой возможности я забыл добавить в качестве 7-го пункта в списке ошибок проектирования языка.
Еще раз повторюсь. Ты еще штук 100 проблем не описал. Многие из них можно объяснить погоней за скоростью (как с переполнением), многие наследием С, ну, и чое что можно списать на нерадивость и упертость Страуструпа и комитета.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[12]: Почему настоящие программисты избегают C++
Здравствуйте, Kubera, Вы писали:
K>Функции, логика которых не предусматривает ошибочных ситуаций, не должны кидать исключений. А функция вычисления среднего арифметического относится как раз к таким. Т.е. предложенное тобой решение с генерацией исключения неверно.
Функция не учитывающая переполенеие уже ошибочна.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[2]: Только настоящие программисты пишут на С++! :)
Здравствуйте, Кодт, Вы писали:
К>1) От компилятора: прекомпиляция заголовков К>2) От программиста: идиома pimpl К>И всё будет летать.
Летает обычно яжыком. А по жизни серьезный проект (более 3 метров кода) компилруется от десяти минут, до часов.
Но я бы назвал галвным недостатком отсуствия модульности невозможность полноценной компонентной разработки. Вот это куда более неприятно. Приходится прибегать к разным КОМ-ам, а они в С++ ой как долеки от нормального программирования.
К>Здесь вообще какой-то пьяный бред написан. При чём тут знаковость/беззнаковость?
Согласен. Но вопрос поднят верно.
К>В любом языке программирования выход за границы массива — это авария. К>Нужно избегать логических ошибок, а не ловить исключения.
В любом кроме С/С++. В нем это всего лишь проход по памяти. А аварии может и не быть. Можно считать это достоинством.
К>Нет, это требует сознательной инициализации. К>Не инициализированная переменная — логический баг.
Не. Не логический. Физический! И еще какой!!! Ой не одну ночь я провел ловя такие баги. Они самые забавные. Сейчас правда по проще стала. Средства контроля стали по приличнее. А раньше был мрак.
К>Вот именно автоматизм конструкторов/деструкторов позволяет обходиться без finally.
Ага. Позволяет. Только процентов 70% программистов плюют на это позволение. За примером далеко ходить не надо. Вот пример подобного кода
Здравствуйте, Glоbus, Вы писали:
G> Я мля не понял мля...!!! А где мля про шаблоны и их хреновую читаемость! А где утечки памяти при пользовании голых указателей! А где отсутсвие сборщика мусора мля!!! Че-то ты старик слабо подготовился, да еще с такими убогими примерами как std::vector::size()! Эй, там, граждане Рима, подготовьте нормально человека для критики плюсов!
Я плякаль, мля.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, d Bratik, Вы писали:
DB>Проблема шалонов не хреновой читаемости, а в том, что они unsafe — невозможно указать ограничений (constraints) для параметров. Шаблонов в своих программах можно избегать. Без сборщика мусора трудно, но существуют подходы (например, концепция владения), которые позволяют обойтись без него. А вот без остального действительно туго.
А я бы вот сборщик мусора поставил бы на второе место после обязательности инициализации переменных. Хто конечно не грабли, но трудоемкость снижает в разы.
Ну, да C++/CLI / МС++ тут частично спасают.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, d Bratik, Вы писали:
DB>>Проблема шалонов не хреновой читаемости, а в том, что они unsafe — невозможно указать ограничений (constraints) для параметров. Шаблонов в своих программах можно избегать. Без сборщика мусора трудно, но существуют подходы (например, концепция владения), которые позволяют обойтись без него. А вот без остального действительно туго.
К>Не умеешь писать с шаблонами — так прямо и скажи.
Ну, это голословные наезды. Я вот вроде немного умею, но, что шаблоны создают не мло проблем. Но тут хоть ясно за что платить.
К>Констрейнты в шаблонах делаются с лёгкостью необычайной.
Это уже даже за гранью спорности. Видимо ты плохо понимашь, что такое констрэйны. В С++ проверки делаются только во время воплощения шаблона. Констрэйны же накладывают ограничения на параметры шаблона. Сдается мне, что в следующей версии стандарта констрэйны добавят обязательно.
К>Как именно — не скажу, тебе это всё равно не пригодится.
О. А еще меня тут пинают за подколки и уколки.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Здравствуйте, d Bratik, Вы писали:
DB>Вы наверное писали очень небольшие программы, без GUI. Для создания программ С++ подходит, но для создания систем — нет.
Учитывая, что Винды вообще на С написаны — это конечно серьезное заявление.
С++ подходит для всего. Ну, почти для всего. Так что вопрос только в цене. Уж очень дорого приходится платить за С++-разработку. В итоге или море глюков, или задержки выхода, или и то и другое.
... << RSDN@Home 1.1.4 beta 3 rev. 279>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.