-2

я использую VisualStudio 2017, но думаю на 2022 ситуация будет та же. Проблема в следующем. Есть файл include.h в котором находятся все остальные дерективы #include, подключается он в main.cpp. Внутри include.h находятся следующие строки

// тут подключаются библиотеки: OpenGL Imgui и множество других
...
// а дальше идут следующие файлы
#include "Lister.cpp"
#include "Game.cpp"
#include "GameLoop.cpp"
#include "Context.cpp"
#include "ContextLoop.cpp"

Все эти файлы я создавал одним и тем же образом, мышью выбирал "добавить новый элемент" в окне "обозреватель решений". Файлы находятся в корневой папке с main.cpp. Проблема в том, что некоторые файлы, например ContextLoop.cpp, не видят имён, объявленных ранее, таких как классы, прототипы функций, пространств и прочего. Т.е. я беру один и тот же код и вставляю по очереди в Context.cpp а затем в ContextLoop.cpp, в первом случае всё работает, во втором нет, причём IDE не жалуется на то, что какой-то из файлов не удалось подключить. Я всегда воспринимал #include как описано на официальном сайте microsoft: введите сюда описание изображения Т.е. на место использования дерективы подставляется полное содержание включаемого файла, ну с некоторыми особенностями работы #pragma once и другими файлозависимыми директивами.

Но как оказалось, есть что-то ещё, что определяет область видимости внутри включаемого файла. P.S. если определить в ContextLoop.cpp, файле, в котором ничего не видно, любую переменную, то из main.cpp и include.h её будет видно, когда как переменной из include.h внутри ContextLoop.cpp видно не будет, но в других файлах видно будет. Есть догадка, что это как-то зависит от .vcxproj файлов проекта.

  • 1
    Если что, код в тексте можно выделять одним апострофом, а не тремя. Принципиальной разницы нет, но так быстрее) – Глеб Jan 22 '24 at 10:49
  • 2
    https://ru.stackoverflow.com/questions/876163#876207 и https://ru.stackoverflow.com/questions/1507820#1507869 и еще где-то был вопрос про циклические зависимости В общем, нужен ликбез по языку. – user7860670 Jan 22 '24 at 11:27
  • Я смог починить тот самый файл при помощи случайного перебора действий, создавая файлы разных расширений и переименовывая/удаляя существующие. В итоге я получил состояние, в котором исходники проекта одни и те же, но есть файлы .vcxproj "до" и "после", где с "до" не работает, а с "после" работает. Внутри файлов небольшие отличия, но именно они отвечают за то, будет ли компилироваться проект, при этом отличия никак не заметны из самой IDE. Чуть позже возможно кратко сформулирую, что это за отличия такие. Да, расширение файлов тут не причём, есть внутренние стейты VS, влияющие на их свойства. – ATtiny13a -PU Jan 22 '24 at 11:30
  • 1
    Компилятор компилирует не только main.cpp (в котором доступны все необходимые объявления за счёт вашего include), но и остальные cpp-файлы, в которых, судя по всему, нет необходимых включений. Обычно включают заголовочные файлы в cpp-файлы, а не наоборот. Поищите какие-нибудь примеры работы с заголовочными файлами. – wololo Jan 22 '24 at 11:36
  • @wololo, иронично, но я пытался следовать этим правилам проектирования, но из-за этих багов автоконфигуратора отказался. Типичный пример, если удалить файл cpp внутри Imgui и снова его вставить с тем же содержимым, проект без вмешательства в конфигурацию больше не скомпилируется, ведь запись о подключении окажется раздельно от остальных его файлов. Надо пользоваться видимо только #include <> и тогда проблем не будет. Сейчас у меня проект без изменения кода с разными .vcxproj либо компилируется, либо нет. Даже названия файлов не менял. Попробую в битом .vcxproj прописать пути в окружение. – ATtiny13a -PU Jan 22 '24 at 11:47
  • @wololo, я сделал, как вы указали, но проект не заработал, зато после указания путей в "дополнительные каталоги включаемых файлов" и подключении файла заголовка через #include <> внутри каждого .cpp, вместо #include "" помогло, буду всегда так делать, спасибо. – ATtiny13a -PU Jan 22 '24 at 12:01
  • 4
    "буду всегда так делать" - не делайте так. Разберитесь в работе препроцессора, в отличиях объявления от реализации, в том, что такое область видимости и т.п. Путаетесь в трех березах, но ругаете при этом компилятор, ide, что угодно, кроме себя. – user7860670 Jan 22 '24 at 12:11

1 Answers1

-1

Проблема заключалась в порядке записи включаемых файлов внутри .vcxproj и .vcxproj.filters, который зависел от порядка действий над файлами в момент создания/добавления внутри проекта из IDE. Ручное исправление порядка текстовым редактором устраняло проблему. Чтобы избежать этой ошибки, можно

  1. использовать функции рефакторинга самой VisualStudio, она создаст гарантированно рабочие пары header source в который можно будет также автоматически перенести существующий код.
  2. включить корневой каталог в список глобальных дополнительных каталогов и подключать файлы через include <>, что исключит влияние .vcxproj, т.к. файл станет внешним.
  3. (плохое решение) удалить/исключить все файлы проекта, а после добавить их в порядке вызовов include, что пересоздаст список внутри .vcxproj в верном порядке.
  4. отказаться от системы сборки MSBuild и использовать Cmake
  • 1
    .filters по большей части влияет только на отображение компонентов в режиме фильтрации в Solution Explorer. Среди перечисляемых в .vcxproj файлов для сборки имеют значения только файлы реализации. А если порядок их перечисления начинает влиять на успешность сборки проекта, то это говорит о наличии ошибок в коде. – user7860670 Jan 22 '24 at 12:19
  • @user7860670, хотелось бы, чтобы проект однозначно не компилировался в случаи ошибки, или чтобы выдавались предупреждения, или документация microsoft говорила, как нельзя делать. Я понимаю, что это выглядит как каприз ребёнка, я понимал с самого начала, что получу за это всё минусы, но я надеюсь, что такой же человек как я хотябы будет знать причину, в чём он был не прав, а не смотреть на магическим образом собирающийся проект и на него же через секунду не рабочий, особенно плохо знакомый с Cmake и внутрянкой VS. – ATtiny13a -PU Jan 22 '24 at 13:23