Форум программистов, компьютерный форум CyberForum.ru

Создание объекта класса сразу после его описания (между "}" и ";") - C++

Восстановить пароль Регистрация
 
SaShka K
3 / 3 / 0
Регистрация: 16.01.2014
Сообщений: 55
11.07.2014, 13:00     Создание объекта класса сразу после его описания (между "}" и ";") #1
Пишу проект с дюжиной хедеров и десятком cpp-шников.
Мне нужны пара объектов класса А, которые должны существовать на протяжении всей программы.
Пытаюсь создать их в хедере сразу после описания класса (так):
C++
1
2
3
4
5
class A {
public:
   int a;
   A(int x=0) : a(x) {}
} objA;   // <-- создание объекта
Проблема - компилятор (MSVS 2013) бросает 2 ошибки:
error LNK2005: "class A objA" (?objA@@3VA@@A) уже определен в Connection.obj E:\_Мои_документы\_CPP Projects\HCS\main.obj HCS
тут main.obj и Connection.obj файлы, соответствующие одноимённым cpp-шникам, в которые включил include'ом хедер, в который вынесен указанный код класса А.
error LNK1169: обнаружен многократно определенный символ - один или более E:\_Мои_документы\_CPP Projects\HCS\Debug\HCS.exe 1 1 HCS
Хедер, само собой, с include-guard'ом.
Пробую экспериментировать: если вынести этот код в main.cpp (перед функцией main()) ошибок нет. Нет их и если вынести его в отдельный хедер, пока инклудю его только в одном месте (например в main.cpp). Но как только добавляю его инклудом в какой-то ещё файл проекта, ошибки появляются.
У меня ощущение, как будто не работает include-guard, но проверил - оформлен он корректно и переменная за #define'ом уникальна в проекте, и других ошибок не сыпется - только эти две.
Помогите пожалуйста разобраться.
Лучшие ответы (1)
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
11.07.2014, 13:00     Создание объекта класса сразу после его описания (между "}" и ";")
Посмотрите здесь:

кто нибудь делал прогу на С++ "Эмулятор клавиш с промежутком времени между "нажатиями""?! C++
C++ После каждой буквы "о" в слове вставить сочетание "ля"
C++ Ошибка экземпляра класса: отсутствие ";" перед идентификатором "o_scenes_1"
Перегрузка "opеrator =" и "{ }" для собственного класса C++
Удалить из двусвязного списка все элементы до первого "*" и после последнего "*" C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
SatanaXIII
Супер-модератор
Эксперт С++
 Аватар для SatanaXIII
5549 / 2563 / 233
Регистрация: 01.11.2011
Сообщений: 6,337
Завершенные тесты: 1
11.07.2014, 13:08     Создание объекта класса сразу после его описания (между "}" и ";") #2
Цитата Сообщение от SaShka K Посмотреть сообщение
objA
Это имя объекта. Который находится внутри вашего
Цитата Сообщение от SaShka K Посмотреть сообщение
include-guard
Следовательно сколько раз у вас вставится ваш хедер, столько одинаковых объектов у вас создастся. О чем вам и говорит ошибка.

Уберите из описательной части вообще любые объявления.
Alex5
883 / 618 / 81
Регистрация: 12.04.2010
Сообщений: 1,552
11.07.2014, 13:17     Создание объекта класса сразу после его описания (между "}" и ";") #3
Сообщение было отмечено автором темы, экспертом или модератором как ответ
Цитата Сообщение от SaShka K Посмотреть сообщение
cpp-шникам, в которые включил include'ом хедер
Включение заголовочного файла в cpp-файл ( #include "a.h" ) эквивалентно копированию его содержимого в cpp-файл.
Цитата Сообщение от SaShka K Посмотреть сообщение
добавляю его инклудом в какой-то ещё файл проекта
Это то же самое, что в двух cpp-файлах определить объект с одним именем (A objA; ).
SaShka K
3 / 3 / 0
Регистрация: 16.01.2014
Сообщений: 55
11.07.2014, 13:52  [ТС]     Создание объекта класса сразу после его описания (между "}" и ";") #4
Спасибо за ответы. Я, кажется, это даже знал, но как-то вылетело. Позвольте, проговорю для уверенности, что понимаю верно:

Т.е. Include-guard НЕ гарантирует, что хедер будет вставлен единственный раз в рамках проекта, а гарантирует то, что он не будет вставлен повторно в рамках единицы компиляции. (т.е. одного cpp-шника со всеми, подтягиваемыми им прямо, или опосредованно хедерами).

Итого - склеиваются все файлы проекта именно в такие единицы компиляции. А точки взаимодействия между этими единицами появляются при вызове из одной из них метода, определённого в другой.
Насколько я далёк от истины?
Спасибо!
SatanaXIII
Супер-модератор
Эксперт С++
 Аватар для SatanaXIII
5549 / 2563 / 233
Регистрация: 01.11.2011
Сообщений: 6,337
Завершенные тесты: 1
11.07.2014, 14:40     Создание объекта класса сразу после его описания (между "}" и ";") #5
SaShka K, если в трех словах, то непосредственно перед компиляцией препроцессор проходит весь текст программы (как именно происходит разбиение на единицы компиляции я не знаю; Evg, может наверное рассказать), раскрывает все инклуды и тупо запихивает весь встречающийся код в один большой длинный текст. Если инклуд защищен, как вы выражаетесь, Include-guard-ом, то он попросту не вставляется в этот текст, если уже одна копия его там имеется. И вот этот уже длинный текст передается компилятору.

Вот здесь можно почитать подробнее: Препроцессорные директивы в C/C++ (#include, #define и прочее)
Очень абстрактное представление о препроцессировании: http://www.cyberforum.ru/attachments/234770d1360839465

Добавлено через 17 минут
А, ну собственно.
DrOffset
6461 / 3835 / 886
Регистрация: 30.01.2014
Сообщений: 6,630
11.07.2014, 14:42     Создание объекта класса сразу после его описания (между "}" и ";") #6
Цитата Сообщение от SaShka K Посмотреть сообщение
Т.е. Include-guard НЕ гарантирует, что хедер будет вставлен единственный раз в рамках проекта, а гарантирует то, что он не будет вставлен повторно в рамках единицы компиляции. (т.е. одного cpp-шника со всеми, подтягиваемыми им прямо, или опосредованно хедерами).
Абсолютно верно.

Цитата Сообщение от SaShka K Посмотреть сообщение
А точки взаимодействия между этими единицами появляются при вызове из одной из них метода, определённого в другой.
Точки взаимодействия разруливает линкер. Именно он и выдал тебе ошибку про повторное определение.

Почитай еще что-нибудь по теме ODR. Это очень важно и напрямую касается твоей темы.

Цитата Сообщение от SatanaXIII Посмотреть сообщение
как именно происходит разбиение на единицы компиляции я не знаю;
Что непосредственно отдано компилятору, то и есть единица трансляции. Компилятор вызывается столько раз, сколько, грубо говоря, задал программист. Если взять, например, проект студии, с 10 cpp файлами в нем, то компилятор будет вызван 10 раз для каждого из этих файлов. Все, что было включено в такой файл и непосредственное содержимое этого файла будет составлять единицу трансляции (итого 10 единиц). Если же мы пишем, например, makefile, то там можно более наглядно посмотреть этот процесс. Можно, скажем, взять за исходный txt-файл. Тогда этот txt и все, что он включает, тоже будет единицей трансляции. Это я к тому, что единица трансляции - это не всегда c или cpp файлы.
SatanaXIII
Супер-модератор
Эксперт С++
 Аватар для SatanaXIII
5549 / 2563 / 233
Регистрация: 01.11.2011
Сообщений: 6,337
Завершенные тесты: 1
11.07.2014, 14:49     Создание объекта класса сразу после его описания (между "}" и ";") #7
DrOffset, все так. Но единица трансляции и единица компиляции - разные понятия. Это меня смущает. ..А хотя да, всякими штуками типа extern это ж все как раз и обходится.
DrOffset
6461 / 3835 / 886
Регистрация: 30.01.2014
Сообщений: 6,630
11.07.2014, 14:56     Создание объекта класса сразу после его описания (между "}" и ";") #8
Цитата Сообщение от SatanaXIII Посмотреть сообщение
Но единица трансляции и единица компиляции - разные понятия.
Это одно и то же. К тому же, термин "единица компиляции" (compilation unit) используется только в паре мест стандарта, в разделе о различиях между С и С++. И там смысл эквивалентен смыслу термина "единица трансляции" (translation unit).
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
11.07.2014, 15:02     Создание объекта класса сразу после его описания (между "}" и ";")
Еще ссылки по теме:

C++ Создать список из целых чисел. После каждого элемента, равного "х" вставить элемент, равный "у"
C++ Сколько существует способов расставить между цифр знаки "+" и "-"
Из слова "яблоко" путем склеек и вырезок его букв получить слова "блок" и "око" C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
olper
24 / 24 / 11
Регистрация: 02.12.2013
Сообщений: 75
11.07.2014, 15:02     Создание объекта класса сразу после его описания (между "}" и ";") #9
Цитата Сообщение от SaShka K Посмотреть сообщение
Т.е. Include-guard НЕ гарантирует, что хедер будет вставлен единственный раз в рамках проекта
Это гарантировано для единицы трансляции. Количество единиц трансляции в проекте - количество *.cpp.
Include-guard может гарантировать что-то на уровне препроцессора. "рамки проекта" ему не ведомы.

Ошибки тебе линковщик сыпет. У него никаких guard-ов нет, есть имена и их надо резольвить. А когда в разных объектниках имена одинаковые как их в кучу собирать?.

"Определение" переменной в программе должно быть только одно. А вот объявлений сколько угодно.
Это добиваются обычно следующим способом
C++
1
2
3
extern int a; // объявление  - можно писать где угодно и сколько угодно раз
int a; // объявление и определение - можно написать только один раз,
        // и надо хорошо подумать на тему того что до первого использования переменную надо "создать".
Yandex
Объявления
11.07.2014, 15:02     Создание объекта класса сразу после его описания (между "}" и ";")
Ответ Создать тему
Опции темы

Текущее время: 16:36. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru