Ответы пользователя по тегу C++
  • Какие посоветуете библиотеки для парсинга исходного кода?

    Nipheris
    @Nipheris Куратор тега C++
    Странный вопрос - логично, что нужно использовать парсеры конкретных языков.
    В принципе, если нужен только разбор в дерево - попробуйте взять ANTLR и грамматики известных языков: https://github.com/antlr/grammars-v4
    Ответ написан
    1 комментарий
  • Как можно подменить вызов функции в классе?

    Nipheris
    @Nipheris Куратор тега C++
    Вызывать обе с помощью указателя на метод. Вы в вопросе уже ответ написали.
    Ответ написан
  • В чем плюсы и минусы классов и библиотек?

    Nipheris
    @Nipheris Куратор тега C++
    Классы, как и процедуры/функции - это простейшие кирпичи для построения дома. Библиотеки - это когда вам подгоняют готовую кухню/ванную или водопровод, который вы встраиваете в ваш дом.

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

    В целом я понял вопрос как "зачем нужны гайки и болтики, если я могу сделать мотор или купить его у мотозавода?". А вы/мотозавод, собственно, из чего будете мотор собирать?
    Ответ написан
    Комментировать
  • Что представляет собой ссылка?

    Nipheris
    @Nipheris Куратор тега C++
    Ну конечно что ждет от вас препод, нам тут все равно не угадать. Я бы как раз и ответил, что это имя для переменной. Я не соглашусь с некоторыми ответами здесь, т.к. не всегда для ссылки компилятор будет выделять память - локальная ссылка на локальную же переменную как раз таки будет просто вторым именем в таблице идентификаторов компилятора при компиляции программы.

    Главная фишка ссылки в том, что это абстрактное l-value, т.е. сущность, в которую можно что-то присвоить (если базовый тип - не константный). То есть ссылка всегда оборачивает какой-либо адрес в памяти, причем на время жизни ссылки этот адрес постоянен (ссылку нельзя "переставить" на другую область памяти). Именно поэтому ссылки всегда нужно инициализировать.
    ЧЕМ инициализировать - другое дело. Можно переменной, а можно - разыменованным указателем.

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

    Теперь попробуем сранить ссылку и другие сущности в языке.
    Определение ссылки vs определение обычной переменной:
    определение обычной переменной это всегда выделение памяти и добавление нового имени в таблицу компилятора для этой области памяти. Определение ссылки - это прежде всего ОПРЕДЕЛЕНИЕ ИМЕНИ, а уже в тех случаях, когда привязку этого ИМЕНИ к АДРЕСУ невозможно осуществить во время компиляции (т.е. например в случае передачи ссылки как параметра функции), то для реализации ссылки применятся указатель. Важно, что компилятор сам выбирает способ реализации поведения ссылки. В любом случае, назначение ссылки - обернуть в l-value уже ВЫДЕЛЕННУЮ память (совершенно не важно, на стеке, куче или где-то еще). Новой памяти для хранения значения целевого типа НЕ выделяется. Если у вас есть переменная и ссылка/несколько ссылок на нее, то при присвоении значения через любую из сущностей вы будете менять одну и ту же область памяти.

    Ссылка vs указатель:
    - самое важное отличие - указатель САМ ПО СЕБЕ является переменной. Под указатель int* компилятор выделит память также, как и под int. Указатель существует сам по себе, ему (если он не const) можно присваивать новые значение, можно присвоить nullptr. Можно даже хранить в нем совершенно некорректный адрес и все будет ок до тех пор, пока вы не разыменуете его. Только когда вы разыменовываете указатель, вы превращаете его в l-value, и с этого момента между ним и ссылкой разницы нет.
    - второе отличие - собственно необходимость разыменования. Т.к. указатель - самостоятельная переменная, для обращения по адресу, на который указатель смотрит, нужно сделать ему *p. Именно в этот момент компилятор начинает рассматривать значение указателя как адрес в памяти, с которым вы собираетесь что-то сделать (если быть совсем точным, но не в момент разыменования, а при попытке чтения/записи. В принципе вы можете даже инициализировать ссылку некорректным указателем, и программа не упадет, пока вы не попытаетесь читать/присваивать по этой ссылке).
    - с учетом сказанного, ссылку можно грубо считать "константым указателем с автоматическим разыменованием". Грубо, т.к. согласно стандарту есть нюансы, такие как вышеупомянутое продлевание жизни временным объектам.
    Ответ написан
    Комментировать
  • Почему выводятся адреса, а не значения?

    Nipheris
    @Nipheris Куратор тега C++
    Я думаю там выводится мусор, а не адреса - с чего вы взяли, что там адреса? Они последовательно идут? Я не думаю.

    *(a-i);//перевести указатель на первый эллемент


    Не, тут не произойдет то что вы пишете. Здесь нет операции присвоения или аналогичной ей. Это просто выражение, результат вычисления которого уйдет в никуда. Совершенно непонятно, зачем вы еще и разыменование поставили. Вы вообще понимаете, что написали там?
    Вам нужно что-то вроде этого: a = npa; или a -= i;
    Ответ написан
    2 комментария
  • Как добавить CA сертификат в Trusted Publisher с помощью WinAPI?

    Nipheris
    @Nipheris Куратор тега C++
    qDebug() << &context;

    Бесполезная операция. В смысле, это, вероятно, не то чего вы хотите добиться. context это на 99% и есть указатель (посмотрите на название типа: PCCERT_CONTEXT, да и всегда можно открыть декларацию этого типа и посмотреть, что там). Если это указатель (что логично, т.к. CertCreateCertificateContext создает некий тяжелый объект, и возвращает вам указатель на него), то нужно вывести сам указатель, а не указатель-на-указатель как сделали вы:
    qDebug() << context;
    И тогда, возможно, вы увидите, что он NULL. А ежели он NULL (что вы должны проверять), то его не стоит передавать параметром в CertAddCertificateContextToStore, т.к. вероятно она ожидает там нормальный объект, и сама не обрабатывает NULL (да и зачем ей это делать). Скорее всего по этой причине в этой функции происходит segfault.
    Ответ написан
    5 комментариев
  • Какую книгу выбрать по сетевому программированию в Qt?

    Nipheris
    @Nipheris Куратор тега C++
    Читайте книги по сетям (а именно - слои OSI, TCP/IP, сокеты, про клиент-серверную архитектуру в целом, кто куда подключается, как передает данные).
    Читайте книги про техническую сторону веба (протокол HTTP, архитектура REST и т.д.).
    Когда вы поймете, что происходит при запросе www.yandex.ru в адресной строке, использовать класс QNetworkRequest не составит никакого труда.
    Ответ написан
    7 комментариев
  • В чем преимущество динамически типизированных языков?

    Nipheris
    @Nipheris Куратор тега C++
    Во многих, даже в большинстве задач, где узким местом не является производительность интерпретатора/рантайма языка, основное преимущество одно: на динамических языках могут писать те программисты, которые не могут на статических. Не в смысле не могут выучить или не понимают, а в смысле - совершенно не хотят. Это что-то такое глубокое в сознании программиста, от чего зависит его выбор динамической/статической типизации (и соотв. языка). Я все больше убеждаюсь, что в зависимости от варианта типизации, программисты, выбравшие для себя "правильный" язык, пишут гораздо более эффективный код.
    У меня, как и у того разработчика из Яндекса (по ссылке в ответе beduin01 ), слишком плохая память для разработки на динамическом языке. Я не могу держать много сущностей в своей голове, чтобы эффективно и правильно использовать динамические языки. Я привык и не могу без хоть каких-нибудь проверок на стадии компиляции (и чем больше, тем лучше).
    Другие считают ограничения статической типизации идиотскими, необходимость создавать всякие непонятные "интерфейсы", чтобы поиметь абстракцию и полиморфное поведение - извращением. Они чувствуют себя легко с объектами и классами. Возможность "прикрутить" любое свойство или метод к существующему объекту вдохновляет их на нестандартные и эффективные архитектурные и инфраструктурные решения.
    Видимо это действительно зависит от особенностей памяти и сознания конкретного человека.

    Разумеется, есть масса технических различий, почитайте остальные ответы.
    Ответ написан
    Комментировать
  • С++. Работа с графикой. Когда начинать?

    Nipheris
    @Nipheris Куратор тега C++
    > Возможно перед работой с любой библиотекой нужно знать "основу" в самом языке?
    Вполне логично, что язык надо знать, вопрос - насколько полно (особенно это касается C++, полностью его знают только разработчики стандарта и компиляторов).
    OpenGL (который я бы советовал вам посмотореть) это по сути Си-шная либа, поэтому с ней проще - выучите что такое функции и указатели, разберитесь с базовыми типами данных и особенностями операций (чтобы не удивляться, почему 3 / 2 = 1, а 3.0 / 2.0 = 1.5), и можете пробовать. Из общего развития - матричная алгебра, особенности компьютерной арифметики (числа с плавающей точкой и т.д.). Ну и сама "графика" - устройство графического конвейера, типы рендеринга (фотореалистичный/реального времени), этапы рендеринга, и т.д.
    Отдельная задача - уметь настроить компилятор и IDE для того, чтобы все, что использует OpenGL, нормально компилилось, но это вы и в гугле найдете.
    Ответ написан
    Комментировать
  • Как создать REST API на C++?

    Nipheris
    @Nipheris Куратор тега C++
    Поддержка HTTP (на базе ASIO), работа с URI и прочие базовые для веба вещи: cpp-netlib.org
    JSON: www.codeproject.com/Articles/20027/JSON-Spirit-A-C... . Есть форки на github.com, много и других библиотек, но лично мне больше эта нравится.

    Первая либа еще не релиз-версии, но API уже стабилизировался, все работает. Более чем годно для малонагруженного сервера (проверено на localhost), можно и для многих посетителей, если поставить за nginx для безопасности.
    P.S. Внезапная альтернатива: FastCGI (https://savannah.nongnu.org/projects/fastcgipp/) + нормальный веб-сервер.
    Ответ написан
  • Почему пропадает член класса?

    Nipheris
    @Nipheris Куратор тега C++
    Вы случайно не забыли там вызвать конструктор базового класса QMapValidator в конструкторе дочернего Class2? Потому что других странностей я не вижу, а вот если вы все-таки забыли, то отработает конструктор по умолчанию (а он есть, если б не было - была б ошибка компиляции), который, конечно, ничего вам не добавит.
    По идее addValid все-таки должен работать - с ним все ок или та же проблема?
    Ответ написан
    1 комментарий
  • Как реализовать класс Directory?

    Nipheris
    @Nipheris Куратор тега C++
    Сложно понять, чего вы хотите добиться. GetFiles - это функция? Она уже определена? Тогда надо так:

    vector<string> files = GetFiles(path, pattern, AllElements);


    То, что вы делаете сейчас - это создание объекта типа vector с передачей его конструктору трех параметров: path, pattern, AllElements

    EDIT: Обновленный код из вопроса компилится без проблем (если определить функцию GetFiles): ideone.com/0RrK6x , нужно уточнить, где ошибка компиляции и посмотреть другой код.
    Ответ написан
    3 комментария
  • Как игровые движки компилируют код?

    Nipheris
    @Nipheris Куратор тега C++
    Вы явно путаете жужжащих мух с теплыми котлетами. Игровые движки создаются разработчиками, также же как и любые другие приложения. Если это игровой движок в классическом понимании (нативный, на D3D или OpenGL) - то это нативное приложение, для создания которого применяются в общем-то обычные хорошо известные инструменты: язык программирования и его тулчейн (компилятор+линковщик) - это минимум, а там уже у кого как - IDE (одну из которых вы упомянули в тегах), просто редактор типа sublime и т.д.
    exe-файл, как и любой другой модуль на любой платформе (PE(exe, dll) на винде, ELF (бинарник/so) на линухе и т.д.) - это результат работы линковщика. Линковщик собирает сгенеренные компилятором объектные файлы и другие библиотеки в такой модуль, объектные файлы генерятся компилятором из исходного кода, исходный код пишут разработчики.
    Для Microsoft Word, Half-Life и KDE в общем и целом этот процесс - одинаковый. Разница только в инструментах, платформах и мелочах.
    Смысл вопроса из заголовка - "как ДВИЖКИ компилируют код?" я так и не понял, если вы имеете в виду скрипты, которые можно выполнять средствами движка - это другая история, многие серьезные двиги используют интепретаторы существующих скриптовых языков (Lua например весьма популярен) или пишут свой для реализации на этом скриптовом языке игровой логики, интерфейсных плагинов (в WoW так делают), ну и так далее.
    P.S. Если уж упомянули в тегах студию, поставьте её, создайте простейший консольный проект (Win32 Console Application), скомпильте и запустите - и вы выполните всю ту цепочку, которую выполняют разработчики нативных приложений (только она у них может быть сложнее, кастомизирована под их нужды, и в их проектах не 2 cpp-файла, а 10 тысяч).
    Ответ написан
    Комментировать
  • C++ загрузка библиотек и dll из определенного файла?

    Nipheris
    @Nipheris Куратор тега C++
    Армянское Радио указал вам правильное направление (т.е. если вы не хотите СРАЗУ грузить dll при запуске exe-шника, а хотите сделать это позже), но вам следует учесть, что:
    1) загружать все равно придется вручную, механизма в C++ для автоматической подгрузки dll именно в момент обращения к функции из нее не существует
    2) загрузка вручную приводит вас к тому, что линковщик не будет связывать ваш exe и dll. Это значит, что вы не сможете пользоваться предварительными объявлениями функций в хедере - вам пригодятся только типы, а указатели на код функций нужно будет получать динамически, как сказал Армянское Радио - по GetProcAddress(). Собственно, это за вас делает ОС при обычной линковке exe и dll.
    3) пункты 1 и 2 разумеется актуальны только для DLL, для тех "DLL", которые на самом деле не DLL, а дотнетовские сборки, свои правила, не имеющие ничего общего с этими (там сборки и так по-дефолту грузятся в момент первого использования типа из этой сборки);

    С учетом всего сказанного, неясно, зачем это вам: в 99% случаев динамическая загрузка нужна для реализации "плагинов" - когда заранее неизвестно, какая DLL будет загружена, чтобы потом можно было без перекомпиляции подсунуть любую DLL, если она экспортирует требуемые функции (для примера - плагины в foobar 2000).
    У вас же нужно вполне конкретно загрузить SFML, так что непонятно зачем вам такие заморочки.
    Ответ написан
    Комментировать
  • Как подключить класс к форме - C++/CLI?

    Nipheris
    @Nipheris Куратор тега C++
    1) в первом блоке кода у вас, возможно, пропущена закрывающая фигурная скобка, проверьте;
    2) если вы создаете окно, то скорее всего оно у вас будет жить относительно долго, и его временем жизни нужно будет управлять вручную. Это значит, вам пора разобраться, что такое указатели и ручное управление памятью/временем жизни объекта (т.е. WindowOpen w(640, 480) скорее всего не годится)
    3) сразу учитесь давать адекватные имена сущностям в программе. WindowOpen это имя для функции, но не для класса, возможно вы имели в виду просто Window.
    4) по возможности не используйте C++/CLI как учебный язык. Это стыковочный диалект C++ для реализации взаимодействия систем поверх .net и нативных - в нем может запутаться даже бывалый C++ разработчик, новичкам даже смотреть на него нельзя - убивает душу. То, что MS по дефолту предлагает проект в студии - это так исторически сложилось. MS сейчас вообще ничего не предлагает адекватного для десктопа под C++, так что мой вам совет: либо C# + WPF/WinForms, либо Qt + C++. SFML вроде бы нормально работает в паре с Qt.
    Ответ написан
    Комментировать
  • Что использовать в С++(Qt,Boost) для простого серверного приложения-хранилища данных?

    Nipheris
    @Nipheris Куратор тега C++
    cpp-netlib.org или doc.qt.io/qt-5/qnetworkrequest.html если нужен HTTP
    Boost::Asio, если не нужно HTTP
    Berkeley Sockets все еще в моде, если не боитесь C-style
    На последние два можно накрутить Protocol Buffers через stream-ы, если протокол достаточно сложный или предполагает расширение.
    Ответ написан
    Комментировать
  • Как правильно составить функцию qHash для объекта содержащего два QString? Или просто какой алгоритм для хеширования двух строк?

    Nipheris
    @Nipheris Куратор тега C++
    А почему такая странная потребность в УНИКАЛЬНОМ хэше (который вы кстати в принципе не получите для двух строк по 20 символов, т.к. хэш-значение - типа uint)?
    > это РАЗНЫЕ объекты, несмотря на то что конкатенация firstName + lastName равна.
    ну и пусть, совпадет один раз, не такой уж частый кейс для имени и фамилии. У вас таких Каримов с одинаковым конкатенированным именем тысяча штук будет?
    Ответ написан
    4 комментария
  • Как лучше реализовать API для модулей?

    Nipheris
    @Nipheris Куратор тега C++
    > Конечно, C++ может вызвать виртуальные методы у указателей
    именно, поэтому вам нужно, как вариант:
    1) сделать абстрактные интерфейсы вроде IFooService, библиотека будет отдавать указатели на объекты, их реализующие
    2) сделать функции-фабрики и функции-уничтожители:
    IFooService* CreateFooService(...);
    void DestroyFooService(IFooService* service);

    Это все нужно в частности для того, чтобы управление памятью не выходило за пределы DLL - иными словами, где порождается, там и убивается. Для большинства библиотек это приемлемое ограничение, которое позволяет сохранять ABI и даже использовать разные рантаймы для DLL и для EXE, его использующего.
    Если вы будете передавать какие-то параметры по указателю, также следуйте этому правилу - не делайте так, что код в EXE выделяет память, а код в DLL - освобождает, и наоборот.
    Ну и вообще, это хорошая абстракция интерфейса (ваш IFooService) от реализации (ваш конкретный класс FooService с конкретным конструктором и деструктором. К-р и д-р сложного класса должны оставаться частью _реализации_).
    Если в качестве параметров, передающихся по значению вы используете struct-ы, это вполне допустимо, но тогда уже надо компилировать DLL и EXE одним компилятором, как этого требует, например, Qt (игнорирование этого правила рано или поздно приведет к странным и трудноуловим ошибкам, связанным с тем, что разные версии компилятора генерируют разный код конструкторов и деструкторов, и вообще могут по разному разложить struct в памяти).
    Ответ написан
    3 комментария
  • При помощи чего разрабатываются интерфейсы для Desktop-приложений?

    Nipheris
    @Nipheris Куратор тега C++
    > Battle.net
    вот очень кстати сказали. Открываем <путь установки>\Battle.net.XXX\, видим:
    2406a0538fd449489e2ffaf0a7f2f05e.png
    Ну вы поняли :)
    А красиво и стильно, это потому что у компании есть деньги на:
    1) специалистов, которые знают и С++, и Qt достаточно хорошо, чтобы придавать приложениям желаемый вид
    2) дизайнеров, которые дадут несколько идей, из которых потом можно выбрать ту, которую реально реализовать, чтобы выглядело на "ура".
    На данный момент Qt это лучшее что я могу посоветовать для плюсов, т.к. с ним реально можно добиться результатов, bnet клиент вам в пример. Приемлемо это для вас или нет - решать вам, меня разработка UI на плюсах нисколько не отталкивает, но это уже личный опыт.
    Ответ написан
    8 комментариев