Способ включения в C ++ с использованием Eclipse - PullRequest
1 голос
/ 18 декабря 2010

Я узнал, что если я компилирую main.cpp, то компилятор просто заменяет все включения фактическим содержимым файла, т.е. #include "LongClassName.h", текстом в этом файле.Это делается рекурсивно в LongClassName.h .В конце концов, компилятор видит огромный «виртуальный» файл с полным кодом всех файлов .cpp и .h.

Но в реальных проектах это кажется намного сложнее.Я посмотрел на Makefile Eclipse, созданный для моего проекта Qt, и кажется, что для каждого файла есть запись с именем file.o и его зависимостями являются file.cpp и file.h .Таким образом, это означает, что eclipse компилирует каждый .cpp отдельно (?)

Означает ли это, что class.cpp ничего не будет знать о глобальных вещах в main.cpp или в классе более высокого уровня, включая hirarchy?

Я наткнулся на эту проблему, пытаясь создать псевдоним для длинного имени класса.Это мой основной класс, и я хотел вызывать статические функции с более коротким именем: Ln :: globalFunction () вместо LongClassName :: globalFunction ()

Iесть класс LongClassName , заголовок которого я включаю в main.cpp.Это основной класс.Все остальные классы включены в него.

LongClassName.h

#define PI 3.14159265

#include <QDebug>

Class LongClassName
{
...
public:
    ...
private:
...
};

typedef LongClassName Ln;

LongClassName.cpp

#include "Class1.h"
#include "Class2.h"
#include "Class3.h"

/*implementations of LongClassName's functions*/

Поэтому я предположил, что когда код включается компилятором в один «виртуальный» файл, каждый класс будет вставлен после этого исходного кода, и поэтому каждый класс должен знать, что Ln является псевдонимом для LongClassName

Это не сработало

Так каков наилучший способ распространения этого псевдонима среди всех классов?

Я хочуизбегать включения LongClassname.h во все классы из-за обратных зависимостей.LongClassName включает в себя все другие классы в своей реализации.И почти все другие классы используют некоторые статические функции LongClassName.

(На данный момент у меня есть отдельный класс Ln , но я пытаюсь объединить его с LongClassName, потому что он кажется более логичным.)

Ответы [ 2 ]

4 голосов
/ 18 декабря 2010

Компилятор знает, как скомпилировать файл .cpp (если это компилятор cpp) в файл .o, называемый «объектный файл», который представляет собой ваш код, переведенный (и, вероятно, обработанный, оптимизированный и т. Д.) На компьютеркод.Фактически компилятор создает ассемблерный код, который транслируется ассемблером в машинный код.

Таким образом, каждый файл cpp компилируется в отдельный объектный файл и ничего не знает о переменных, объявленных в других файлах cpp, если только вы не включитедекларации, о которых вы хотите, чтобы объектный файл знал, либо в файле cpp, либо в h-файле, который он включает.

Хотя компиляция выполняется отдельно для каждого cpp, компоновщик связывает все объектные файлы с одним исполняемым файлом (или библиотеки), поэтому переменная, объявленная в глобальном пространстве имен, действительно является глобальной, и каждое объявление, явно не помещенное в именованное пространство имен, помещается в глобальное пространство имен.

Вероятно, вам будет полезно прочитать обо всех этапах«компиляция», например, здесь: http://www.network -theory.co.uk / docs / gccintro / gccintro_83.html

3 голосов
/ 18 декабря 2010

В конце компилятор видит огромный «виртуальный» файл с полным кодом всех файлов .cpp и .h.

Это неправильно.В .cpp s вы должны включать только .h s (или .hpp s, если хотите), почти никогда не .cpp s;.h в общем случае содержит только объявления классов и методов, а не их фактическое тело 1 (т.е. их определение ), поэтому, когдавы компилируете каждый .cpp, компилятор все еще ничего не знает об определении функций, определенных в других .cpp s, он просто знает их объявление, и с его помощью он может выполнять синтаксические проверки, генерировать код для вызовов функций, ... нотем не менее он сгенерирует «неполный» объектный файл (.o), который будет содержать несколько «заполнителей» («здесь идет адрес этой функции, определенной где-то еще», «здесь идет адрес этой внешней переменной» и т. д.)

После того, как все объектные файлы были сгенерированы, именно компоновщик должен заботиться об этих заполнителях, соединяя все объектные файлы вместе и связывая их ссылки с реальным кодом (которыйтеперь можно найти, поскольку у нас есть все объектные файлы).

Для получения дополнительной информации о классическом cмодель компиляции + ссылки, см. здесь .

Означает ли это, что class.cpp ничего не будет знать о глобальных вещах в main.cpp или в классах более высокого уровня, включая hirarchy?

Да, именно так.

Но почему Makefile, созданный eclipse, просто не скомпилирует main.cpp.Почему этого недостаточно?main.cpp содержит все зависимости.Зачем компилировать каждый .cpp отдельно?

main.cpp содержит не весь код, а только объявления.Вы не включаете весь код в один и тот же .cpp (например, путем включения других .cpp s), главным образом, чтобы уменьшить время компиляции.классы из-за обратных зависимостей.LongClassName включает в себя все другие классы в своей реализации.И почти все другие классы используют некоторые статические функции LongClassName.

Если вы используете защиту заголовков, у вас не должно быть проблем.

1. Хорошо, они также содержат встроенные и шаблонные функции, но они являются исключением, а не правилом.

...