3 / 3 / 0
Регистрация: 16.01.2014
Сообщений: 55
|
||||||
1 | ||||||
Создание объекта класса сразу после его описания (между "}" и ";")11.07.2014, 13:00. Показов 1861. Ответов 8
Метки нет Все метки)
(
Пишу проект с дюжиной хедеров и десятком cpp-шников.
Мне нужны пара объектов класса А, которые должны существовать на протяжении всей программы. Пытаюсь создать их в хедере сразу после описания класса (так):
Пробую экспериментировать: если вынести этот код в main.cpp (перед функцией main()) ошибок нет. Нет их и если вынести его в отдельный хедер, пока инклудю его только в одном месте (например в main.cpp). Но как только добавляю его инклудом в какой-то ещё файл проекта, ошибки появляются. У меня ощущение, как будто не работает include-guard, но проверил - оформлен он корректно и переменная за #define'ом уникальна в проекте, и других ошибок не сыпется - только эти две. Помогите пожалуйста разобраться.
0
|
|
11.07.2014, 13:00 | |
Ответы с готовыми решениями:
8
В зависимости от времени года "весна", "лето", "осень", "зима" определить погоду "тепло", "жарко", "холодно", "очень холодно" После каждого знака препинания (".", ",", ";") вставить в строку пробел, если там его нет
Вставить пробел после каждого символа "." "," "!" или "?", если за этими символами не следует пробел |
Почетный модератор
![]() 5850 / 2861 / 392
Регистрация: 01.11.2011
Сообщений: 6,907
|
|
11.07.2014, 13:08 | 2 |
Это имя объекта. Который находится внутри вашего
Следовательно сколько раз у вас вставится ваш хедер, столько одинаковых объектов у вас создастся. О чем вам и говорит ошибка.
Уберите из описательной части вообще любые объявления.
1
|
1130 / 789 / 232
Регистрация: 12.04.2010
Сообщений: 2,012
|
|
11.07.2014, 13:17 | 3 |
![]() Решение
Включение заголовочного файла в cpp-файл ( #include "a.h" ) эквивалентно копированию его содержимого в cpp-файл.
Это то же самое, что в двух cpp-файлах определить объект с одним именем (A objA; ).
1
|
3 / 3 / 0
Регистрация: 16.01.2014
Сообщений: 55
|
|
11.07.2014, 13:52 [ТС] | 4 |
Спасибо за ответы. Я, кажется, это даже знал, но как-то вылетело. Позвольте, проговорю для уверенности, что понимаю верно:
Т.е. Include-guard НЕ гарантирует, что хедер будет вставлен единственный раз в рамках проекта, а гарантирует то, что он не будет вставлен повторно в рамках единицы компиляции. (т.е. одного cpp-шника со всеми, подтягиваемыми им прямо, или опосредованно хедерами). Итого - склеиваются все файлы проекта именно в такие единицы компиляции. А точки взаимодействия между этими единицами появляются при вызове из одной из них метода, определённого в другой. Насколько я далёк от истины? Спасибо!
0
|
Почетный модератор
![]() 5850 / 2861 / 392
Регистрация: 01.11.2011
Сообщений: 6,907
|
|
11.07.2014, 14:40 | 5 |
SaShka K, если в трех словах, то непосредственно перед компиляцией препроцессор проходит весь текст программы (как именно происходит разбиение на единицы компиляции я не знаю; Evg, может наверное рассказать), раскрывает все инклуды и тупо запихивает весь встречающийся код в один большой длинный текст. Если инклуд защищен, как вы выражаетесь, Include-guard-ом, то он попросту не вставляется в этот текст, если уже одна копия его там имеется. И вот этот уже длинный текст передается компилятору.
Вот здесь можно почитать подробнее: Препроцессорные директивы в C/C++ (#include, #define и прочее) Очень абстрактное представление о препроцессировании: https://www.cyberforum.ru/atta... 1360839465 Добавлено через 17 минут А, ну собственно.
1
|
17410 / 9246 / 2260
Регистрация: 30.01.2014
Сообщений: 16,178
|
|
11.07.2014, 14:42 | 6 |
Абсолютно верно.
Точки взаимодействия разруливает линкер. Именно он и выдал тебе ошибку про повторное определение. Почитай еще что-нибудь по теме ODR. Это очень важно и напрямую касается твоей темы. Что непосредственно отдано компилятору, то и есть единица трансляции. Компилятор вызывается столько раз, сколько, грубо говоря, задал программист. Если взять, например, проект студии, с 10 cpp файлами в нем, то компилятор будет вызван 10 раз для каждого из этих файлов. Все, что было включено в такой файл и непосредственное содержимое этого файла будет составлять единицу трансляции (итого 10 единиц). Если же мы пишем, например, makefile, то там можно более наглядно посмотреть этот процесс. Можно, скажем, взять за исходный txt-файл. Тогда этот txt и все, что он включает, тоже будет единицей трансляции. Это я к тому, что единица трансляции - это не всегда c или cpp файлы.
1
|
Почетный модератор
![]() 5850 / 2861 / 392
Регистрация: 01.11.2011
Сообщений: 6,907
|
|
11.07.2014, 14:49 | 7 |
DrOffset, все так. Но единица трансляции и единица компиляции - разные понятия. Это меня смущает. ..А хотя да, всякими штуками типа extern это ж все как раз и обходится.
0
|
17410 / 9246 / 2260
Регистрация: 30.01.2014
Сообщений: 16,178
|
|
11.07.2014, 14:56 | 8 |
Это одно и то же. К тому же, термин "единица компиляции" (compilation unit) используется только в паре мест стандарта, в разделе о различиях между С и С++. И там смысл эквивалентен смыслу термина "единица трансляции" (translation unit).
2
|
27 / 26 / 16
Регистрация: 02.12.2013
Сообщений: 79
|
||||||
11.07.2014, 15:02 | 9 | |||||
Это гарантировано для единицы трансляции. Количество единиц трансляции в проекте - количество *.cpp.
Include-guard может гарантировать что-то на уровне препроцессора. "рамки проекта" ему не ведомы. Ошибки тебе линковщик сыпет. У него никаких guard-ов нет, есть имена и их надо резольвить. А когда в разных объектниках имена одинаковые как их в кучу собирать?. "Определение" переменной в программе должно быть только одно. А вот объявлений сколько угодно. Это добиваются обычно следующим способом
1
|
11.07.2014, 15:02 | |
Помогаю со студенческими работами здесь
9
Реализовать классы "Воин", "Пехотинец", "Винтовка", "Матрос", "Кортик" (наследование)
С++ консольное приложение win32, матерится на первое "pow" после "if", а на "system" говорит что неопределён. Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |