Если ваш код выполняется без AttributeError
s, то, вероятно, Visual Studio дает ложные срабатывания. Если так, игнорируйте их. Это происходит потому, что статический анализ динамического кода не всегда делает правильно.
Поскольку это - быстрое, грязное и неэлегантное решение проблемы интерфейса по сравнению с реализацией.
Это полагается полностью на Препроцессор C, который является о самом тупом инструменте в секции.
Другие решения избегают следующих проблем:
Dviljoen думает, что я вполне строг с ним, и он прав. Это - почти 40-летний дизайн с эры перфокарт и перфоленты. Существует невероятная сумма высококачественного программного обеспечения, созданного в C/C++ с помощью расположения источника/заголовочного файла, несмотря на все потенциальные глюки и упомянутые выше проблемы.
Поскольку это означает копировать информацию, которую можно получить от исходного кода. Другие языки стараются избегать этого дублирования кода.
В мои старые дни C я сделал то же. Я хранил всю информацию в своих.c файлах и использовал мелкий инструмент для генерации заголовочных файлов от них во время нормальной сборки.
В случае C#, 3,0 состояний спецификации
Поскольку блок является единицей самоописания функциональности, содержащей и код и метаданные, нет никакой потребности в #include директивах и заголовочных файлах в C#. Открытые типы и участники, содержавшиеся в конкретном блоке, сделаны доступными в программе C# просто путем ссылки на тот блок при компиляции программы.
Поскольку они - остатки от прошлого.
Использование современного языка понятие модулей и пакетов.
Если Вы хотите использовать функцию/класс, это определяется в другом файле, импортируйте тот файл. Компилятор выясняет символы (т.е. имена) так, чтобы можно было использовать их.
Подход C/C++: извлечение функция/определения классов вручную и помещает их в другой файл, затем сделайте текстовое включение тех определение где угодно, Вы хотите использовать их.
В C Вы не можете сделать ссылки вперед, т.е. использовать функцию, еще не определенную выше ее использования. Заголовки первоначально сделаны для который как ссылки на реализацию.
Я посмотрел на принятый ответ вопроса, на который ссылаются, и это правильно. Но сегодня, скорость компиляции является незначительной проблемой (кроме, возможно, с очень крупными приложениями: это берет 1/4hr для очистки, компилируют приложение, которое мы имеем, по крайней мере, в Windows). И детали реализации скрыты так или иначе, мы обычно смотрим только на документацию API, т.е. видимый интерфейс.
Для истории я видел некоторые библиотеки C++, реализованные в 99% в заголовках (только имеющий .cpp файлы, где система запросила их), таким образом имитируя стиль Java (C# не был здесь в то время...).
Я сказал бы, что, идеально, вся информация должна жить в единственном месте и иметь систему модуля, которая разумно постарается не перекомпилировать/импортировать ненужные детали и затем иметь компилятор смочь извлечь информацию только для интерфейса при необходимости (например, поставляться с библиотекой или безотносительно).
Они не действительно необходимы в C# и Java, потому что можно указать, что уровень доступа для каждого метода (например, общедоступный или частный), и помимо Вас имеет отражающую способность как Вы, не делают в C++.
Обратите внимание, что для методов не-ООП с помощью заголовочных файлов не действительно настолько плохо. Можно, например, только объявить, какие функции должны быть общедоступными клиентам в заголовочных файлах при сохранении других скрытыми (и поэтому недоступный), только объявив их в .cpp или.c файле.
Я сказал бы, что большинство языков OO получает весь пробег, в котором они нуждаются вдоль этих строк от наличия Интерфейсов. Это обеспечивает всю гибкость (т.е. - разделение интерфейса от реализации) заголовочных файлов при наличии более строгих контрактов с клиентами, использующими интерфейсы (потому что они осуществляются языком/компилятором).
Мне заголовки в C и C++ являются приемником производительности и достижением. Компиляция... кричит, забыл фиксировать подпись метода. Компиляция... кричит, потребность добавить метод к классу X.
Для избавлений от заголовков вывод компилятора должен содержать описание кода, который может понять сам компилятор. Это не было легко с компоновщиками старшего возраста: объектные файлы, которые они использовали, не могли быть слишком умными. Следовательно задачу создания описания кода оставили человеку: заголовочный файл.
Более новые языки любой обход, компоновщик в целом (интерпретируемые и языки VM) или использует пользовательских компоновщиков (Turbo Pascal, я принимаю Delphi также). Однако, даже сейчас, когда Вы имеете дело с компоновщиком (или его младший одноуровневый элемент, динамический загрузчик библиотеки), необходимо произвести своего рода описание того, что в библиотеке.
Большинство других языков не является почти столь же тупым и трудным проанализировать и скомпилировать как C++, таким образом, там "оптимизация производительности" разделения заголовка и реализации не так важна.
В C/C++ заголовочные файлы являются в основном способом сгруппировать переменные, которые должны были бы иначе быть объявлены как экстерны в каждой единице компиляции, что они используются.
Это однако не ограничило сложность или разнообразие проблемных областей, которые может обработать C/C++. Его просто, что язык программирования развил тот путь. В конечном счете все, что имеет значение, - то, что компоновщик так или иначе выясняет все ссылки и тип переменных, которые Вы использовали в своей программе.
Путем C/C++ делает это довольно сыро по сравнению с новой обрезкой языков программирования, которые, кажется, имеют поддержку родного языка обработки вне ссылок на переменные и методы.