FAQ C ++ - отличный ресурс обо всех особенностях C ++, но он, вероятно, немного более продвинут, чем вы ищете - большинство вопросов (не только ответов) - загадки даже довольно опытным разработчикам C ++.
Я думаю, что если вы заглянете в учебники по C ++, вы сможете что-то найти. Вы также можете попробовать изучать язык ассемблера (или, по крайней мере, получить краткое представление о том, как на самом деле происходит в микропроцессоре), поскольку и C, и C ++ довольно близки к аппаратному обеспечению в том, что они делают. В этом их скорость и мощь, но они достигаются ценой некоторых из более привлекательных абстракций, которые предлагает Java.
Я могу попытаться ответить на ваши конкретные вопросы, заданные выше, но я не знаю, насколько хорошо я сделаю.
Одним из ключей к пониманию взаимосвязи между заголовочными файлами и файлами cpp является понимание идеи «модуля перевода». Файл класса Java может рассматриваться как единица перевода, поскольку это базовая единица, которая компилируется в двоичную форму. В C ++ почти каждый файл cpp является единицей перевода (есть исключения, если вы делаете странные вещи).
Файл заголовка может быть включен в несколько единиц перевода (и должен быть включен везде, где используется то, что определено в заголовке). Директива #include буквально просто выполняет подстановку текста - содержимое включенного файла вставляется дословно, где находится директива #include. Обычно вы хотите, чтобы ваш интерфейс класса был определен в заголовочном файле, а реализация - в файле cpp. Это потому, что вы не хотите раскрывать детали своей реализации другим переводчикам, которые могут включать заголовок. В C ++ все, включая классы, на самом деле не являются богатыми объектами, а просто кусками памяти, которым компилятор присваивает значение ... компилируя одинаковую информацию заголовка в каждую единицу перевода, компилятор гарантирует, что все единицы перевода имеют такое же понимание того, что представляет собой кусок памяти. Из-за нехватки богатых данных после компиляции такие вещи, как отражение, невозможны.
Вторым шагом в процессе сборки C ++ является компоновка, в которой компоновщик берет все скомпилированные единицы перевода и ищет символы (обычно вызовы функций, но также и переменные), используемые в единице перевода, но не определенные там. Затем он ищет другую единицу перевода, которая определяет этот символ, и «связывает» их вместе, так что все вызовы конкретной функции направляются в единицу перевода, которая ее определяет.
В случае методов класса они должны вызываться через экземпляр класса, который за кадром является просто указателем на фрагмент памяти. Когда компилятор видит эти типы вызовов методов, он выводит код, который вызывает функцию, неявно передавая указатель, известный как указатель this
, функции в качестве первого аргумента. У вас могут быть функции, которые не относятся к классам (как вы сказали, не к методам, потому что метод должным образом является функцией-членом класса и, следовательно, не может существовать без класса), поскольку компоновщик не имеет понятия о классе. Он увидит блок перевода, который определяет функцию, и другой, который вызывает функцию и связывает их вместе.
Это оказалось намного дольше, чем я ожидал, и, конечно, это упрощение, но оно является точным, насколько мне известно, и предоставленным уровнем детализации ... надеюсь, это поможет некоторым. По крайней мере, это должно дать вам отправную точку для поиска в Google.