fk0> Абстракция в коде может быть воплощена либо в абстрактном базовом классе, fk0>либо в шаблоне. В большинстве случаев более рационален подход с шаблоном, так fk0>как даёт связывание/диспетчеризацию в момент компиляции, а не в момент исполнения. fk0>Кроме того, в момент разворачивания шаблона он обладает полнотой знания о переданном fk0>ему классе-параметре, что тоже может использовать и что не доступно в варианте fk0>с наследованием.
У меня большой опыт как на с/с++, так и на c#.
На c# намного удобнее читать/писать бизнес логигу (или другую логику, где много разных сущностей и классов), так как не приходиться лазить по 2-м файлам, а всё можно исправить и увидеть в одном файле.
Хотелось бы иметь возможность на с++ такую же как на c#.
Использование абстракций и шаблонов, что-бы описать всё в одном файле, сильно усложнит код — это не то!
c# — это современный язык, в котором учли, что более удобно иметь 1 файл, чем 2. Не пойму, почему с++ не хочет дать такую возможность ? Оставить возможность h/cpp тем кому нравиться это и для совместимости.
Здравствуйте, maks1180, Вы писали:
M>>По любому, один из классов будет только ссылаться на другой, ссылка или указатель — это уже детали. Более того, я чего-то сомневаюсь, что в каком-либо языке такое вообще возможно
M>Ты себя крутым считаешь, всех хаишь — сам бред полный написал. Такое невозможно скомпилировать, так возникает бесконечная вложенность в данных. M>Я вот что имеел ввиду:
class B;
template <typename B> class A_
{
// If you uncomment this line and other commented line
// in class B compilation fails:
// B data[sizeof(B)];public:
// This function will be compiled after template instantiation,
// and complete definition of the class defined by template.
//
// Template instantiation is delayed until template first time used.void DoSomething()
{
m_v = B::GetV();
}
private:
int m_v;
};
using A = A_<B>;
class B
{
// If you uncomment this line and other commented line
// in class B compilation fails:
//A bb;
// This compilation failure caused by the fact that line
// listed above causing template instantiation, but
// template can't be instantiated if it requires knowledge
// of sizeof(B), as class B currently is not fully defined.public:
static int GetV() { return 1; }
// But this function will be compiled only after finishing definition
// of class B.void DoSomething()
{
// Template will be instantiated after compiler sees this line.
A a;
a.DoSomething();
}
};
Конечно тебе нужен не прямо вот такой трюк, но этот трюк демонстрирует
возможный подход. A и B для противоположного класса должно быть какой-то
абстракцией, интерфейсом, параметром шаблона.
Здравствуйте, Mystic Artifact, Вы писали:
MA>Здравствуйте, maks1180, Вы писали:
MA>Для меня основной минус C# от которого хотелось бы избавиться — это чудовищная организация кода. MA>Открываешь файл — там класс на 1K+ строчек, и понять, что вообще там за методы или свойства есть —
Вот для этого-то в C++ и есть заголовочные файлы!
А то заладили, модули, модули. И будет то же самое. И, кстати, в C# есть понятие .ref
файлов и в них те же "хедеры". В студии по F11/F12 оно кстати показывать их умеет...
S>Есть ещё виртуальные методы. При оверрайде их в классах наследниках приходится повторно прописывать те же аргументы по несколько раз. И при изменении в базовом классе тянуть все изменения везде.
А если бы ты так не делал, то как компилятор бы отличал виртуальные методы от других
перегруженных функций с тем же именем? А никак. Тогда нужно забыть об ADL (argument
dependent lookup). А это важное свойство C++ которого нет у многих других.
S>В си++ не хватает такой штуки, как прототип функции.
Forward declaration для функции возможен. Вот tentative declarations для переменных нет.
Какие проблемы?
S>Второе. S>При использовании модулей отпадает необходимость в .h файлах и инклюдах. Всё можно делать только в .cpp S>Кроме дифайнов — их нельзя экспортировать из модулей. Вот их как раз и можно выносить в .h
Нет. Я не понимаю, как с этим в модулях, но некоторые вещи же принципиально
не являются кодом. Например шаблоны. Как шаблон может быть в CPP, какой в этом смысл?
Шаблон -- это сущность лежащая в своём совершенно ортогональном пространстве шаблонов,
которое ортогонально пространствам типов и "вещественных" объектов таких как переменные
и функции.
Здравствуйте, maks1180, Вы писали:
M>У меня большой опыт как на с/с++, так и на c#. M>На c# намного удобнее читать/писать бизнес логигу (или другую логику, где много разных сущностей и классов), так как не приходиться лазить по 2-м файлам, а всё можно исправить и увидеть в одном файле.
Во-первых не в одном. Там есть partial классы и потом концов не найдёшь, не то, что не в одном
файле, а вообще непонятно даже в какой DLL-ке...
Во-вторых чем оно удобно, когда есть файл на 50000 строк и там всё вперемешку.
Без IDE по такому файлу навигация невозможна, а если ты код поменял, пока редактировал,
что он стал синтаксически некорректным (скобок не хватает), то и IDE развалится и
перестанет работать... Сомнительное удобство.
И наконец, повторюсь, в C# есть .ref файлы и студия по F11/F12 что-то такое показывает.
Наподобие хедеров. Удобно на самом деле.
M>Хотелось бы иметь возможность на с++ такую же как на c#.
Пустяковый вопрос. Весь код пишешь в хедер-файле. И будет как в C#.
M>Использование абстракций и шаблонов, что-бы описать всё в одном файле, сильно усложнит код — это не то!
Это как раз то, так как реализует один из принципов SOLID. Даже программисту проще,
так как вместо сложной сущностьи с непонятным объёмом свойств появляется простая абстракция
с очень ограниченным интефейсом. Надо просто однажды сломать мозг и уйти от FORTRAN-мышления
и императивного программирования. И понимать, что компьютерная программа -- это пирамида
абстракций положенных друг на друга, где связи в большинстве случаев выражаются относительно
простыми декларациями. И всё станет на свои места. Надо просто уметь перемещаться по слоям
этой пирамиды и видеть в пределах одного уровня вверх-вниз.
А с FORTRAN-мышлением сколько-нибудь сложную архитектуру вообще не выстроить. Так как там
всё и всегда со всем связано, всё нужно держать в голове, получается монолит который
невозможно в будущем никак модернизировать, нет разделения на слои, соответственно отдельные
слои и протестировать отдельно невозможно, только всё в комплексе. Мрак.
M>c# — это современный язык, в котором учли, что более удобно иметь 1 файл, чем 2.
Абсолютно любую C++-программу можно вообще записать в ОДНОМ ФАЙЛЕ. Просто тупо
склеить файлы. Разделение на файлы лишь для удобства человека и раздельной компиляции.
M> Не пойму, почему с++ не хочет дать такую возможность ? Оставить возможность h/cpp тем кому нравиться это и для совместимости.
Потому, что она объективно практически не нужна. И как не хочет -- про модули разговор
который год. Но в них смысл немного другой, избавиться от многократного парсинга скорей.
Так как с раздельной компиляцией в C++ реально плохо, из-за того, что половина кода в хедерах.
Здравствуйте, maks1180, Вы писали:
M>>>Хотелось бы иметь возможность на с++ такую же как на c#.
fk0>> Пустяковый вопрос. Весь код пишешь в хедер-файле. И будет как в C#.
M>Нет, не будет он компилиться. Я привёл код выше который не компилируется без шаблонов и прочих хитростях. M>Вот он M>http://www.rsdn.org/forum/cpp/8161507.1
Дело не в файлах, а как раз в "прочих хитростях". А во-скольки файлах оно всё записано
как раз дело десятое.
Можно в одном файле вначале:
1) декларировать класс;
2) потом отдельно записать определения функций.
И всё сразу начнёт компилироваться. Всё дело только в том, в каком порядке всё вынужден
обрабатывать компилятор. Если код писать как есть -- то начале "компилируется" класс, а потом
его функции. И в этот момент выясняется, что B -- неизвестная вещь. Если код фунцкии записать
отдельно, после класса, и после определения B -- всё получится. А шаблон позволяет сделать
то же самое, но неявным образом: финт в том, что шаблон компилятором не компилируется в код
до момента первого его использования. Поэтому внутри шаблона можно написать какой-то код,
но он не вызовет вопросов в момент интерпретации самого шаблона до момента пока шаблон
не превратиться в класс. И второй момент: все функции класса компилируются после того как
класс полностью определён. Вот и всё что нужно знать.
От файлов зависит что-то только для C-кода где полагаются на глобальные static-переменные.
Но они вообще не нужны, для этого существуют неймспейсы. Да, есть подводный камень -- анонимный
(без имени) неймспейс один на весь файл.
Ещё есть глобальные, в пределах модуля то-есть, static-функции. Тоже специфическая штука,
так как они молча перекрывают глобальные же не-static-функции (досталось в наследство от C),
а функции из неймспейса так не могут. Но это реально тонкости нужные в отнюдь не в прикладном
программировании...
Резюмируя: хедеры -- это удобно, так как виден интерфейс. Если кому-то неудобно потому,
что там какой-то очень развесистый интерфейс, то скорей вы делаете что-то очень плохое
в архитектурном плане и менять нужно используемые архитектурные паттерны, а не требовать
чего-то от языка. Единственной реальной проблемой на мой взгляд является очевидное неудобство
реализации PIMPL-идиомы, но оно вытекает в значительной степени из-за того, что компилятор должен
знать layout класса и, главное, его sizeof. Может быть, имеет смысл такой финт ушами, когда
конструктор в PIMPL спрятан таки за фабрикой класса, но при этом предоставляется кастомный
аллокатор со стороны вызывающей стороны...
Здравствуйте, LaptevVV, Вы писали:
M>>Приходиться одно и тоже писать (название функций) в h и в cpp файлах. И менять тоже нужно в двух местах. LVV> LVV>Я с этим столкнулся еще в 1992 году...
Я чуть раньше столкнулся... но в 1994 растолкнулся — перешел на Дельфи
Здравствуйте, maks1180, Вы писали:
M>1) часто на сервере нужно править исходники. Там только текстовый терминал.
Шта?
Какой сервер? К чему он указан? Мы точно про С++ говорим?)
M>2) современные IDE, часто имеет проблемы если использовать макросы или шаблоны.
Если мы говорим про современные — то не часто, крайне нечасто. Причём если проблемы есть — то там ещё под вопросом проблемы логики автора.
M>3) Я привык клавитатурой работать быстро, а тут нужно мышкой править через IDE — это дольше и неудобнее.
Все ИДЕ имеют хоткеи, дублирующие функциональность мышки. И серьёзно — упомянутая разница в скорости работы с мышкой\клавиатурой в процессе разработки не важна в принципе.
M>4) И намного удобнее когда 1 файл = 1 класс.
Это говорит только о небольшом опыте работы с С++. Есть свои ньюансы. В большинстве случаев всё же удобнее разделение по файлам из-за анонимных неймспейсов и управлением вложениями классов.
Мой совет — просто научиться пользоваться средствами ИДЕ и данные проблемы уйдут как класс.
Здравствуйте, fk0, Вы писали:
S>>Второе. S>>При использовании модулей отпадает необходимость в .h файлах и инклюдах. Всё можно делать только в .cpp S>>Кроме дифайнов — их нельзя экспортировать из модулей. Вот их как раз и можно выносить в .h
fk0> Нет. Я не понимаю, как с этим в модулях, но некоторые вещи же принципиально fk0>не являются кодом. Например шаблоны. Как шаблон может быть в CPP, какой в этом смысл? fk0>Шаблон -- это сущность лежащая в своём совершенно ортогональном пространстве шаблонов, fk0>которое ортогонально пространствам типов и "вещественных" объектов таких как переменные fk0>и функции.
При использовании модулей шаблоны как раз нормально размещаются в .cpp файлах.
Re[3]: Большой минус С++ (бинд аргументов функции)
Здравствуйте, fk0, Вы писали:
fk0>Здравствуйте, Sm0ke, Вы писали:
S>>Есть ещё виртуальные методы. При оверрайде их в классах наследниках приходится повторно прописывать те же аргументы по несколько раз. И при изменении в базовом классе тянуть все изменения везде.
fk0> А если бы ты так не делал, то как компилятор бы отличал виртуальные методы от других fk0>перегруженных функций с тем же именем? А никак. Тогда нужно забыть об ADL (argument fk0>dependent lookup). А это важное свойство C++ которого нет у многих других.
Я про то что хочется такую возможность как "забиндить" типы аргументов и их имена у функции на некое имя. Чтобы в дальнейшем можно было этот бинд использовать.
Здравствуйте, netch80, Вы писали:
MA>> Публичный контракт из C# или Java получить совершенно точно не представляется возможным, пока вы не выполните работу компилятора. N>Хм, как правило в этих обоих языках _публичный_ контракт выделяют в виде сущности типа interface. По крайней мере так ну очень рекомендуется. А уже отнаследоваться от интерфейса — сделать реализацию — можно и только на нужные методы. N>Конечно, никто не заставляет так делать, и внутри пакетов на это поплёвывают.
Библиотеки, обычно не делают интерфейсы на каждый публичный тип, т.к. в этом, часто просто нет смысла (исходя из использования).
Да, это частично парируется, в C#, например, ч.з. internal interface. Но всё таки, добавлять это только лишь для организации кода — врядли будет нормальным, с точки зрения рантайма или общепринятых практик.
А для структур и вовсе надо 3 раза подумать, прежде чем наделить её (публичным) интерфейсом.
MA>> В реальности — в проектах — есть одна директория куда навалено по заветам FDG — т.е. все в одну кучу, N>Реально есть такой завет?
Не думаю, что есть прямые заветы про директории — есть заветы про нэймспейсы (что вполне обоснованно).
Но студия, из коробки, считает, что структура директорий и нэймспейсов совпадают, что приводит, к тому что или проекты тупо следуют этому правилу, либо мудрят что-то руками (например свои шаблоны, правильные экстеншны эту мелочь решают — но оба вариант на любителя, а в самой студии/проектной системе всё никак не сделают настройку, хотя и просят уже много лет).
В последнее время, сверху этого появился такой вот анализатор: dotnet_style_namespace_match_folder, так что при должном усердии, это можно ещё и превратить в ошибку компиляции.
MA>> и если вы это видите все в первый десяток раз — то никакие средства IDE — не помогут, не говоря уже о том, что IDE нужна когда нужна но не более. А если код логически расформирован — то внезапно уже и IDE не нужна что бы понять что и где. N>Ну при определённом уровне сложности с IDE таки в разы легче
Потенциальную пользу от IDE я не отрицаю, да и всех я не видел всё равно. В студии есть очень много хорошего, и иногда пользуюсь, хотя есть и досадные баги.
N>Я конечно извиняюсь, и не придирка, но: https://dictionary.cambridge.org/dictionary/english/header N>Ну нету там "и".
Спасибо, принято. По русски это всё равно правильно писать не так.
Здравствуйте, fk0, Вы писали:
fk0> А то заладили, модули, модули. И будет то же самое. И, кстати, в C# есть понятие .ref fk0>файлов и в них те же "хедеры". В студии по F11/F12 оно кстати показывать их умеет...
reference assemblies — это трюк компилятора, служащий только для того, что бы компилятор не грузил реальные сборки во время компиляции.
Т.е. в любом случае они не учавствуют в компиляции кода самой сборки, и соответственно они не используются для валидации её как таковой.
Да и на сегодня — они генерируются автоматически (прямо сборки), как продукт компиляции, которая потом легко залетит в nuget-пакет, опять таки, ради оптимизиации потребления пакетов.
Со стороны выглядит похоже, но служит другим целям.
Здравствуйте, AeroSun, Вы писали:
M>>1) часто на сервере нужно править исходники. Там только текстовый терминал.
AS>Шта? AS>Какой сервер? К чему он указан? Мы точно про С++ говорим?)
Как раз для софта на C++ такое вероятнее, чем на многих других языках.
Причём часто сервер одновременно embedded в смысле малых ресурсов.
M>>3) Я привык клавитатурой работать быстро, а тут нужно мышкой править через IDE — это дольше и неудобнее. AS>Все ИДЕ имеют хоткеи, дублирующие функциональность мышки. И серьёзно — упомянутая разница в скорости работы с мышкой\клавиатурой в процессе разработки не важна в принципе.
Зато графика в сотни раз прожорливее по трафику.
Хотя это нивелируется тем, что в некоторых IDE можно сделать ремотное управление по ssh+gdb...
M>>4) И намного удобнее когда 1 файл = 1 класс. AS>Это говорит только о небольшом опыте работы с С++. Есть свои ньюансы. В большинстве случаев всё же удобнее разделение по файлам из-за анонимных неймспейсов и управлением вложениями классов.
Так разделение по какому принципу-то?
AS>Мой совет — просто научиться пользоваться средствами ИДЕ и данные проблемы уйдут как класс.
Её надо по-вашему запускать на целевом хосте, или как?
Здравствуйте, fk0, Вы писали:
fk0>Здравствуйте, maks1180, Вы писали:
M>>У меня большой опыт как на с/с++, так и на c#. M>>На c# намного удобнее читать/писать бизнес логигу (или другую логику, где много разных сущностей и классов), так как не приходиться лазить по 2-м файлам, а всё можно исправить и увидеть в одном файле.
fk0> Во-первых не в одном. Там есть partial классы и потом концов не найдёшь, не то, что не в одном fk0>файле, а вообще непонятно даже в какой DLL-ке...
но это же не обязательная фича и используется только там где надо(на моей памяти, так обычно делили авто-генерённый код и ручной). Лежит в той же сборке
fk0> Во-вторых чем оно удобно, когда есть файл на 50000 строк и там всё вперемешку. fk0>Без IDE по такому файлу навигация невозможна, а если ты код поменял, пока редактировал, fk0>что он стал синтаксически некорректным (скобок не хватает), то и IDE развалится и fk0>перестанет работать... Сомнительное удобство.
ага, но зачем такое длинное?
если у вас файлы по 50 тысяч строк, .h файл вам не поможет.
Здравствуйте, Marty, Вы писали:
MA>> Со стороны выглядит похоже, но служит другим целям. M>Каким? И чем это отличается от плюсовых хидеров? Тем, что генерятся автоматически?
Тем, что это исключительно служит целям оптимизации процесса компиляции (скорость, память и т.п. — ему банально нужно будет грузить/молотить меньше, и сервер компилятора будет держать меньше памяти в итоге).
Тем, что это позволяет иметь "targeting pack" не имея реальных сборок которые могут быть использованы в рантайме (так, имея установленный .NET 4.8, мы легко можем таргетится на .NET 4.5), но в рантайме мы всегда используем 4.8.
Тем, что это это изначально вызвано не сколько причинами выше, а тем, что .NET 4.x и BCL имеют достаточно интересную стратегию деплоймента (in-place), которая решила одни проблемы, но породила другие.
От плюсовых заголовков это отличается тем, что это не является частью языка. Reference assembly — это обычная сборка (.dll), откуда удалены все незначимые метаданные и детали. Т.е. тел методов нет, и доступны только публичные типы. Точно так же вместо этого можно использовать реальные сборки, как это и делалось ~10 лет назад, абсолютно ничего не потеряв.
А в рамках одной сборки (assembly) — это вообще не нужно. Это даже не нужно в рамках одного солюшена с сотней проектов.
Здравствуйте, netch80, Вы писали:
N>Здравствуйте, AeroSun, Вы писали:
M>>>1) часто на сервере нужно править исходники. Там только текстовый терминал.
AS>>Шта? AS>>Какой сервер? К чему он указан? Мы точно про С++ говорим?)
N>Как раз для софта на C++ такое вероятнее, чем на многих других языках. N>Причём часто сервер одновременно embedded в смысле малых ресурсов.
Вообще невероятно, из раздела особо фантастичной фантастики.
Про embedded — это вообще файспалм.
Я понимаю, что про С++ ходит много слухов, но всё на самом деле не так
M>>>3) Я привык клавитатурой работать быстро, а тут нужно мышкой править через IDE — это дольше и неудобнее. AS>>Все ИДЕ имеют хоткеи, дублирующие функциональность мышки. И серьёзно — упомянутая разница в скорости работы с мышкой\клавиатурой в процессе разработки не важна в принципе. N>Зато графика в сотни раз прожорливее по трафику. N>Хотя это нивелируется тем, что в некоторых IDE можно сделать ремотное управление по ssh+gdb...
Это всё из разряда "сделать из буханки троллейбус". Вы выдумываете проблемы, которых в реальной жизни у разработки на С++ не существует.
AS>>Мой совет — просто научиться пользоваться средствами ИДЕ и данные проблемы уйдут как класс. N>Её надо по-вашему запускать на целевом хосте, или как?
... не могу понять — это прикол или серьезно спрашивате?)