Pull to refresh

Comments 65

это язык, иерархия изменений в котором прослеживается вплоть до 1973 года, когда он был изобретён.

Я как самый объективный и не ангажированный программист из всей статьи, прикопаюсь конечно же к дате:)

С++ начинает отсчёт с 1983. Точнее Бьярни начал в это время, франкештеить экспериментировать с С, внедряя разные штуки. Что в итоге породило самый лучший язык программирования Pascal С++.

Около 1974 года Деннис Ритчи закончил работу над языком, который был следующим этапом эволюции после B и назвал его C.

История C++ начинается в 1979 году, в рамках докторской диссертации Страуструп решил создать инструмент, который был бы производительным, но при этом обеспечивал абстракцию. Его первой разработкой стал C with Classes.

В 1982 году он решил доработать C with Classes, чтобы язык мог работать над проблемой распределенных вычислений. Так появился C++.

Изначально C++ не был полноценным языком. Это был пакет препроцессоров для языка C.

Первый публичный релиз 1985 года, Cfront 1.0, был довольно приличным, но чтобы пользоваться им, надо было быть экспертом в C, чтобы не сломать свой же код.

К 1987 году GCC 1.15.3 начал поддерживать C++, а в 1989 году появился Cfront 2.0, который был гораздо лучше первой версии пакета.

В 1990 году был создан комитет ANSI C++, а в 1991 году – комитет ISO C++. В итоге появились C++98/03, затем C++11, затем C++14, C++17, C++20, и так далее.

https://tproger.ru/articles/istoriya-cpp-s-1953-goda

Две недели спустя нам удалось на экране единственный статичный голубой квадратик

А вот на ps1 для этого требовалось пол года:) Вполне быстро.

За всё время работы с Rust я пользовался отладчиком, может быть, однажды, вся остальная отладка шла через printf.

Вот тут я что-то не уловил. В чём заключается сложность расставить брейкпойнты и запустить отладку Раста нажатием одной кнопки в VSCode, как вы описали это для C++?

Вы не понимаете, это другое:)

Другое - это, например, Кложур. Вот там отладка действительно при первом знакомстве вызывает взрыв головы)

Я тут на ночь, погуглил кложур. Чёт сложно... Мозг отказывается понимать.

В чём заключается сложность расставить брейкпойнты и запустить отладку Раста нажатием одной кнопки в VSCode, как вы описали это для C++?

Совсем не улавливаете иронии в статьи? Вся статья же пропитана ею.

Так это ирония и сатира, понял

Этот текст в основном - ненавязчивый подкол C++. В данном месте автор подразумевает, что в Rust'е типа отладка практически не требуется... (Ну, по моему опыту потребность в отладчике на Rust'е действительно гораздо меньше, и отладочного вывода часто достаточно там, где на C++ уже очень хочется отладчика.)

Впрочем, надо отметить, что перевод текста не очень хороший, и он частично замыливает иронию и сарказм (не только по отношению к C++, но и к Rust'у, и к самому себе), достаточно неплохо поданные в оригинале.

Мне выше уже писали что вся статья - сплошная ирония, но, если честно, даже перечитав по второму кругу я не уловил ни иронии, ни стёба. Похоже, пора в отпуск.

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

Коллега, мне растаманы карму обнулили за правду в глаза.😆

А я всего лишь утверждаю, что 80% якобы проблем плюсов надуманы, остальные 20 решаются знанием языка и избеганием его тёмных возможностей, особенно начиная с С++11.

Так же мой поинт в том, что создателям раст нужно пойти и крепко подумать, что они употребляли, работая над синтаксисом и названием некоторых сущностей, типа Rc и Аrc.

Ваши утверждения корректны только в случае, если вы работаете над проектом САМИ. А если людей много, то идёт забив, т.к. у каждого программиста своё понятие, что важно, а что нет. Можно, конечно, неугодных расстреливать, но так будет большая текучка кадров))

что 80% якобы проблем плюсов надуманы, остальные 20 решаются знанием языка и избеганием его тёмных возможностей, особенно начиная с С++11.

Не, ну в любом языке 95% проблем решаются знанием языка :)

В данном месте автор подразумевает, что в Rust'е типа отладка практически не требуется... (Ну, по моему опыту потребность в отладчике на Rust'е действительно гораздо меньше, и отладочного вывода часто достаточно там, где на C++ уже очень хочется отладчика.)

Ну тут ирония если и есть, то только наполовину. Я в своё время (пару лет назад) был бы рад использовать IDE с отладчиком, но вместо этого был вынужден пользоваться отладочной печатью из-за регулярных "съезжаний" точек останова и <not available> вместо значения переменной в lldb, хотя переменная на соответствующей строке была безусловно available. Сейчас вроде с этим получше, но сейчас я на расте практически не пишу. А уж в то время Visual Studio (не Code) реально был глотком свежего воздуха с его рабочими брейкпоинтами и удобной интроспекцией переменных по сравнению с растом.

Вот кстати только что попробовал ради любопытства rust-gdb в консоли, вот для сравнения сначала C++:

Отладка программы на C++
$ cat hello.cpp
#include <iostream>

void foo()
{
    constexpr int x = 100;

    std::cout << x << std::endl;
}

int main(int argc, char **argv)
{
    foo();

    return 0;
}

$ g++ -o hello -g hello.cpp

$ gdb hello
[... шапку я выкинул ...]
Reading symbols from hello...
(gdb) break foo
Breakpoint 1 at 0x1175: file hello.cpp, line 5.
(gdb) run
Starting program: /home/oleg/tmp/hello

This GDB supports auto-downloading debuginfo from the following URLs:
  <https://debuginfod.ubuntu.com>
Enable debuginfod for this session? (y or [n]) n
Debuginfod has been disabled.
To make this setting permanent, add 'set debuginfod enabled off' to .gdbinit.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, foo () at hello.cpp:5
5           constexpr int x = 100;
(gdb) n
7           std::cout << x << std::endl;
(gdb) p x
$1 = 100
(gdb)

Точка останова по имени функции работает, печать значения constexpr переменной тоже работает. Теперь раст:

Отладка программы на Rust
$ cat src/main.rs
fn foo()
{
    const X : i32 = 100;

    println!("{}", X);
}

fn main()
{
    foo();
}

$ cargo build
   Compiling hello-rs v0.1.0 (/home/oleg/tmp/hello-rs)
    Finished dev [unoptimized + debuginfo] target(s) in 0.43s

$ rust-gdb target/debug/hello-rs
[... шапку я тоже выкинул ...]
Reading symbols from target/debug/hello-rs...
(gdb) break foo
Function "foo" not defined. <- Хрен
Make breakpoint pending on future shared library load? (y or [n])
(gdb) break *foo
No symbol 'foo' in current context <- Хрен-2
(gdb) break 3
Breakpoint 1 at 0x8d90: file src/main.rs, line 5. <- Ну хоть это работает
(gdb) run
Starting program: /home/oleg/tmp/hello-rs/target/debug/hello-rs

This GDB supports auto-downloading debuginfo from the following URLs:
  <https://debuginfod.ubuntu.com>
Enable debuginfod for this session? (y or [n])
Debuginfod has been disabled.
To make this setting permanent, add 'set debuginfod enabled off' to .gdbinit.
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, hello_rs::foo () at src/main.rs:5
5           println!("{}", X);
(gdb) print X
No symbol 'X' in current context <- Хрен-3
(gdb)

Не работает ничего из вышеперечисленного - по крайней мере из коробки, может быть, какими-то дополнительными приседаниями можно чего-то добиться. Да, если заменить const на let, то печать будет работать, но ведь для C++ constexpr переменная прекрасно печатается!

Вот этот тезис из начала треда не совсем верен:

В данном месте автор подразумевает, что в Rust'е типа отладка практически не требуется... 

Из другой статьи автора:

I tend to stick to printf debugging because Rust debuggers are still pretty bad, so that's a wash for me. But in languages with good debugger support, I can see how this style might be a bit of a pain.

Так что тут вряд ли написано с иронией - прямо сказано, что дебаггер плюсов лучше

Ну вообще кстати брейкпоинт работает, если указывать полное имя (hello_rs::foo), а не сокращенное. Но значение const-символа мне напечатать в отладчике пока так и не удалось.

На мой взгляд, одно другому не мешает. Как я написал в "начале треда", автор иронизирует и над c++, и над Rust, и над собой. :)

Если посмотреть на контекст в той статье, ссылку на которую Вы дали, то там тоже звучит "мне-то норм, я привык отладчиками не пользоваться". Но в целом -спасибо, пожалуй, перечитаю статью ещё раз - может, там действительно меньше иронии, чем мне показалось.

Debugger плохой, иногда пропускает части кода, или в ассемблер кидает. В Rustrover также...

Ставишь бряку в файле xxx.rs подключаешь какую нибудь зависимость где есть файл с тем же именем и твоя бряка срабатывает в обоих. Я как то неудачно назвал файл очень популярным именем и получилось что одна бряка срабатывала в 5 местах - можете сами представить насколько это помогает отладке.

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

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

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

Сейчас еще готовят замену Rust и без borrow checker'a и проще (мнение авторов).
искать по YT, название: Hylo - The Safe Systems and Generic-programming Language Built on Value Semantics - Dave Abrahams
Также, Graydon Hoare (автор Rust), со слов Sean Parent в подкасте, положительно высказался о Hylo...

Интересно, если Rust - убийца C++, то убийцы Rust - также убийцы C++? Поддерживается ли транзитивность. А еще Hylo звучит интересно... "Какой твой язык основной?" - "Ху..ло." - "Что, простите?".

Хайло же, что в русском, конечно, "гораздо" лучше

Создаём класс GameObject, затем объекты GameObject, представляющие собой квадраты, жёстко вписанные в плиточную карту. Далее относим квадраты к подклассу  SquareObject, делаем объекты SquareObject

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

наверно потому что к наследованию это не имеет отношения.

Я думаю тут автор акцентировал внимание на динамическом полиморфизме. А наследование просто один из способов достичь этого в C++

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

Некто Эрик Липперт написал такой же пример, доказывая, что DDD/ООП полная хрень. Но доказал лишь, что правильно высосанный из пальца пример доказывает что угодно.

Так тут цель обучения вообще новичка, начиная с языка. Сразу пытаться объяснить Entity-Component-System, пропуская "наивные" объектные реализации, чревато тем, что у обучаемого не будет всей картины, зачем всё это нужно, и какие проблемы решает.

Резюмирую недостатки С++ с точки зрения автора:

  • Недостатков самого языка нет

  • Нет общепринятых подходов к сборке и управлению зависимостями из-за распространённости на куче платформ (и, иногда, трудновато понимать тексты ошибок, хотя в большинство современных компиляторов вполне неплохо их выводят).

Добавлю от себя: вскользь читаю куда идёт многопоточка в с++26 и понимаю что надо садиться за книжки и лабораторные работы, не смотря на приличный стаж с этим языком. Хотя в целом идеи правильные.

Недостаток инструментария по нашим временам - это недостаток языка. :)

CMake + vcpkg/conan решают 99% вопросов. Просто этим тоже надо уметь пользоваться, как и языком. А для тех кому слишком сложно - есть какой нибудь js или python :)

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

Ну извините. В вашем мире походу вообще должна быть только одна операционка, одна архитектура с одним набором инструкций и тп. Одних способов деплоя под линукс вон сколько, не говоря о винде и маках.

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

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

Ну извините. В вашем мире походу вообще должна быть только одна операционка, одна архитектура с одним набором инструкци...

Это вы о чём?

Так же в вашем идеальном мире...

Откуда вы про идеальный мир взяли? Пакетные менеджеры и средства сборки это что-то что есть в применяющихся на практике ЯП.

Я не говорю, что это хорошо, что в плюсах это не совсем тривиально

Вы по крайней мере не считаете это проблемой, а если кто-то считает, то "пусть идёт программировать на языках для ненастоящих программистов".
(Я ни в коем случае не адвокат js и питона, просто вы тут ложную дихотомию устроили).

Но это достаточно гибко и всё зависит от потребностей

Да и в языках с менеджерами зависимостей всё гибко. Только там не надо ломать голову над типовым сценарием, всё работает из коробки.

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

  • explicit, [[nodiscard]] и пр. должны быть по умолчанию

  • У лямбд нет короткого синтаксиса

  • enum class вовсе не class

Конечно язык развивается, но zip_view, expected, статические operator[],() появились только в C++23. Рефлексию и pattern matching все ещё ждём. Надеюсь что они получатся лучше чем корутины, которые ещё долго можно будет рассматривать как недостаток языка.

А лямбды чем не угодили?

При передаче даже простых функторов в алгоритмы вроде std::transform лябмды очень многословны. Меня устраивает явный захват переменных, но иногда хочется чего-то более простого.

В Cpp2 Герб Саттер сформировал очень приятный синтаксис, единый для функций и лямбд. Если вкратце, то auto в аргументах функции опционален и предполагается по умолчанию. Хотя меня и немного расстраивает отсутствие возможности явного захвата, сам синтаксис приятнее текущего.

вкратце, то auto в аргументах функции опционален и предполагается по умолчанию

а какой конкретно? auto, auto& или auto&&?

Для обьектов размером не более 2 указателей эквивалент `const auto`. Для обьектов большего размера `const auto&`.

В Cpp2 аргументы обладают дополнительной классификацией, in, copy, out, inout, move, forward. В зависимости от этого применяются соответствующие классификаторы. По умолчанию in.

Добавил бы, ещё спецификатор const для переменных по-умолчанию

С explicit не будет работать часть низкоуровневых либ по софтварной эмуляции чего-то. Так же не будет работать математика, что значит писать так больше нельзя int x = (3.14 + у)*2, и надо будет учитывать все конверсии, что выглядит как лютый заморочь. А ещё с explicit не работает добрая половина способов инициализации перемнной, буквально ограничивая тебя 1-2 способами.

С [[nodiscard]] ты не сможешь пользоваться даже memcpy, ибо он неожиданно возвращает указатель который ты ему же и передал. Многие функции ОС тоже что-то возвращают и придётся писать кучу веток кода по обработке сколько символов в консоли ты написал, иначе тебе варнингов на пол экрана намолюет.

С лямбдами сложно, ибо в целом можно сделать чтоб компилятор сам строил лямбды, но это будет не везде решаемо. Мол как угадать переменная ссылка или значение? А это важно между прочим. Можно было бы сделать новый синтаксис как в С#, но для лямбд без захвата, тогда было бы прикольно, согласен.

С енумами непонятки какие-то, ибо это "отдельная сущность". Но всё же логично что класс означает что это "объект сам в себе с explicit кастом в дефолтный енум или специальный тип". Хотя меня бы устроило если бы дефолтный енум не сыпал своими членами в пространство имён, хотя это может через классы эмулировать, лол.

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

explicit по умолчанию не значит отсутствие возможности обозначить конструктор как implicit используя ключевое слово или атрибут.

[[nodiscard]] не препятствует игнорированию аргументов по умолчанию, а лишь вызывает предупреждение. После введения _ плейсхолдера в C++26 или используя каст в void.

enum class X{}; уже не экспортирует свои значения в окружающее пространство имён, и не конвертируется имплиситно из/в нижележащий тип. Но у него все ещё не может быть членов, что делает работу с ним менее удобной.

Меня тут только explicit напрягает. Мол включить некоторые предупреждения по умолчанию это полезно, да, но не для explicit. Это буквально сломает добрую часть С++. Слишком много логики завязано на этой фиче и просто так запретить её было бы странно.

Лучше бы добавили правило в варнинги, мол тип который не является агрегатом должен указывать явно explicit он или нет. Тогда бы вещи типа С-структур бы работали, а вот всякие самописные менеджеры чего-либо - нет. Всё ещё бы потребовало переписывать кучу кода, но зато было бы +- понятным почему так сделано.

Все жду когда сделают передачу параметров в функцию по имени... Такая простая вроде вещь, даже в примитивном T-SQL от майков есть, а в плюсы так и не завезут... Приходится либо как-то агрегировать параметры, либо экзотику городить. Или может в новых стандартах что-то поменялось и уже не надо принудительно писать 30 дефолтных значений аргументов только для того, чтобы указать недефолтное 31-е значение ?.. :(

надо принудительно писать 30 дефолтных значений аргументов только для того, чтобы указать недефолтное 31-е значение

а вы уверены что тут проблема в отсутствии такой фичи в языке...?

/s

Вопрос был про фичу в языке... И на 10 параметрах споткнуться можно, а это уже более распространенный случай, правда ? За 20 лет эволюции кода кровавого энтерпрайза всякие монстры могут вырасти ...

Вам не нужны 10 отдельных параметров. Используйте в качестве параметров структуры с default значениями, а для них designated initializers.

Имена параметров как в C так и в C++ - это по сути своей опциональная вещь, важная только внутри самой функции, и больше нигде. При объявлении прототипов их допустимо вообще не указывать (а я встречал организации, где такое даже задано местными гайдлайнами). Далее, скажем, в std имена параметров не являются частью контракта, только типы являются, поэтому в разных реализациях std от разных компиляторов у одних и тех же функций будут разные имена параметров (а в каких-то случаях их вообще не будет). Никто не будет реализовывать фичу, которой нельзя надёжно пользоваться даже с std.

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

Имена параметров стираются из определений функции, ниже корректный код

// include 1
void f(int x, int y);

// include 2
void f(int y, int x);

// implementation
void f(int a, int b)
{
}

И это печально...

Если вас пре-процессор устроит, можете себе накостылить такое

void fn(int x = 11, int y = 12, int z = 13)
{
}

struct fn_Params
{
        int x = 11;
        int y = 12;
        int z = 13;
};

#define FN(...) { fn_Params p { __VA_ARGS__ }; fn(p.x, p.y, p.z); }

int main()
{
        FN(.y = 3, .z = 2);
        return 0;
}
//https://godbolt.org/z/57MvKrd5o
#include <print>

struct fn_Params
{
        int x = 11;
        int y = 12;
        int z = 13;
};

void fn(const fn_Params& p)
{
  std::println("x={}, y={}, z={}", p.x, p.y, p.z);
}

int main()
{
        fn({.y = 3, .z = 2});
        return 0;
}

О, и без препроцессора!

Можно использовать назначенную инициализацию, если допустимо передать один объект вместо кучи параметров - https://compiler-explorer.com/z/orM9sh9de

Сорри, только после отправки заметил что это дубль - https://habr.com/ru/articles/844988/#comment_27330472

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

С одной стороны, можно все эти обёртки объявить как inline и компилятор соптимизирует. С другой стороны, если брать ваши случаи, под 10-30 параметров в функцию, они передаются через стек, и там без разницы - эти параметры лежат в стеке просто последовательно, или в той же самой памяти в стеке, но оформленные в структуру.

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

По тексту ошибок могу добавить, что текст зависит от компилятора. И иногда, чтобы понять о чём идёт речь, легче собрать несколькими компиляторами один модуль. Текст ошибок отличается и где-то в одном случае лучше написано у Clang, где-то у GCC

А ещё разные компиляторы по-разному выдают warnings. Некоторые из них полезны тоже по-разному, а некоторые очень даже помогают найти реальные ошибки и проблемы.

Из свежего - clang указал, что в цикле for (auto const var... делается копия большой переменной var, хотя к ней можно было бы обращаться по ссылке. Другие компиляторы этого не заметили.

Я, как обычно, придерусь к качеству перевода. Я понимаю, что это беда всех современных толмачей, которые заведомо не понимают смысла переводимого текста. Чукча не читатель, чукча переводчик. Но всё равно обидно, когда читаешь текст, и не можешь понять, откуда в нём вдруг взялась "большая аудитория". Приходится лезть в оригинал, где всё логично - аудитория превращается в "прекрасную возможность", поскольку "почти любую концепцию из C++ легко понять, если объяснить её в ключе «о, эта как та штука из Rust»."

"Ask questions later" означает совсем не "а уже потом переходили к вопросам". К вопросам тут никто и не собирается подходить. Это классические "надмозги", над которыми Гоблин так угорал в 90-е. Розетта Стоун. Причем если читать текст, а не только переводить его, то буквально парой абзацев объясняется подход "На нём можно написать код сейчас, а поправить потом", который здесь и реализуется. В виде "сделаем статическую переменную, а о недостатках этого решения подумаем когда-нибудь потом". Отложим в долгий ящик.

моя сестра была так не склонна учить C++

Шта? Мы только что читали, что она упёрлась рогом и будет учить только C++! Так склонна или нет? Оказывается склонна, а в тексте на самом деле "сообщения об ошибках были, пожалуй, самым большим затруднением в изучении С++, если не считать проблем со сборкой". Причем здесь уже задача даже не на понимание, а тупо перевод - impediment к желаниям и склонностям никакого отношения не имеет.

И так весь текст.

" она будет сидеть за отладкой ошибок сегментирования",

А может и не будет, C++ не настолько страшен, как Си, где может всё питание выгореть к х-м, вообще проблемы С++ две - 1) каждая библиотека типа stl, qt, boost епёт на свой манер, попробуй разберись, 2) избыточная лексика, для обратной совместимости, чего не стоило бы делать , на мой взгляд, к примеру для чего необходимо вводить две сущности шаблонов typename и class (object pascal даже отказался от семантики Object в пользу Class), почему надо давать описание каждой переменной в интерфейсе функции, если переменные имеют одинаковую семантику, это только самое бвдоражущее, могу накидать ещё)

boost как раз таки во многом следует принципам и стилю stl.

А qt это альтернатива stl, поэтому различия вполне оправданы

к примеру для чего необходимо вводить две сущности шаблонов typename и class

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

object pascal даже отказался от семантики Object в пользу Class

А вот тут не тот случай, тут действительно разная семантика: object может быть размещен на стеке, а class - только в куче.

почему надо давать описание каждой переменной в интерфейсе функции, если переменные имеют одинаковую семантику

Не совсем понял, о чем вы.

Вот что происходит, если изменить сигнатуру функции в заголовке, а в файле .cpp этого не сделать – и наоборот.

Что случится? Qt Creator сразу подсветит.

Sign up to leave a comment.

Articles