Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Определение переменной в заголовочном файле 
V
    Опции темы
Alchimik
Дата 18.1.2011, 19:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 1.12.2009

Репутация: нет
Всего: 0



Интерес по большей части теоретический. Есть два фала .cpp, оба подключают head.h
Код

#include <iostream>
#include "head.h"
using namespace std;
void f ();
int main()
{
    cout << x << endl;
    f();
}


Код

#include <iostream>
#include "head.h"

void f ()
{
    std::cout << x << std::endl;
}

Вот содержимое подключаемого файла:
Код

#ifndef HEAD_H
#define HEAD_H
int x = 5;
#endif 

Возникает ошибка множественного определение переменной x. Вопрос - почему возникает ошибка? По моему разумению, раз int x = 5; находится в блоке ifndef ... endif, то и определяться переменная x должна только один раз, а при повторном подключении заголовочного файла блок ifndef ... endif должен игногрироваться, как будто его там и нет.

PM MAIL   Вверх
KaraKum
Дата 18.1.2011, 19:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 640
Регистрация: 3.12.2007

Репутация: нет
Всего: 1



Объявление переменной "x" нужно выделить в "info.cpp" и подключать к проекту так же как и любые другие .cpp-файлы. А там где эта переменная используется нужно писать перед началом её использования:
Код

extern int x;


Добавлено @ 19:44
В этом примере переменная объявляется 2 раза потому что подключается загаловочный файл 2 раза. По одному разу в каждом .cpp-файле.

Это сообщение отредактировал(а) KaraKum - 18.1.2011, 19:45
PM MAIL WWW   Вверх
Alchimik
Дата 18.1.2011, 19:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 1.12.2009

Репутация: нет
Всего: 0



Цитата(KaraKum @  18.1.2011,  19:43 Найти цитируемый пост)
В этом примере переменная объявляется 2 раза потому что подключается загаловочный файл 2 раза. По одному разу в каждом .cpp-файле.

Я согласен, заголовочный файл подключается два раза, но раз обявление переменной стоит в блоке ifndef ... endif, при втором подключении заголовочного файла разве не должно содержимое этого блока игнорироваться?


ps: наверно вы имели в виду "определяется 2 раза"

Это сообщение отредактировал(а) Alchimik - 18.1.2011, 19:54
PM MAIL   Вверх
Фантом
Дата 18.1.2011, 20:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: 4
Всего: 49



Цитата(Alchimik @  18.1.2011,  19:51 Найти цитируемый пост)

Я согласен, заголовочный файл подключается два раза, но раз обявление переменной стоит в блоке ifndef ... endif, при втором подключении заголовочного файла разве не должно содержимое этого блока игнорироваться?

"Препроцессор" на то и "пре", что он работает до компилятора, а не после. При попытке все это собрать происходят две независимых компиляции, соответственно, и препроцессор отрабатывает два раза независимо друг от друга. А ошибку множественного определения находит линковщик, к моменту запуска которого вся компиляция уже закончена.
PM   Вверх
Alchimik
Дата 18.1.2011, 20:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 1.12.2009

Репутация: нет
Всего: 0



Цитата(Фантом @ 18.1.2011,  20:11)
"Препроцессор" на то и "пре", что он работает до компилятора, а не после. При попытке все это собрать происходят две независимых компиляции, соответственно, и препроцессор отрабатывает два раза независимо друг от друга. А ошибку множественного определения находит линковщик, к моменту запуска которого вся компиляция уже закончена.

Я себе представлял процесс так: сначала препроцессор обрабатывает первый файл .cpp, доходит до строки #include "head.h", оббрабатывает файл head.h и результат вставляет вместо #include "head.h". Во время обработки head.h препроцессор встречает строку #ifndef HEAD_H, переменная HEAD_H, такчто она определяется (#define HEAD_H). Получается вместо #include "head.h" препроцессор вставляет в первый файл строку int x = 5; 
Затем препроцессор обрабатывает второй .cpp файл, дойдя до #include "head.h" он снова обрабатывает файл head.h, но в этот раз переменная HEAD_H определена, поэтому всё что находится между #ifndef HEAD_H и #endif пропускается. Т.е. вместо #include "head.h" препроцессор вставляет пустую строку. Но если так рассуждать, никакого множестваенного определения переменной нет.

Вы говорите что "препроцессор отрабатывает два раза независимо друг от друга", то есть при обработке второго файла он уже "не помнит" что переменная HEAD_H была определена во время обработки первого файла?
PM MAIL   Вверх
mes
Дата 18.1.2011, 20:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



каждый юнит (.cpp) транслируется (компилируется) отдельно, а потом уже выходные файлы собираются (линкуются) в конечный (.exe)..



--------------------
PM MAIL WWW   Вверх
Alchimik
Дата 18.1.2011, 21:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 1.12.2009

Репутация: нет
Всего: 0



 smile понял
KaraKumФантомmes, спасибо за помощь
PM MAIL   Вверх
БелАмор
Дата 18.1.2011, 21:36 (ссылка)  | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 209
Регистрация: 10.6.2010
Где: Россия

Репутация: нет
Всего: 17



Цитата(KaraKum @  18.1.2011,  19:43 Найти цитируемый пост)
А там где эта переменная используется нужно писать перед началом её использования:
extern int x;

Это нужно писать в h-файле.
PM   Вверх
Alchimik
Дата 18.1.2011, 21:52 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 1.12.2009

Репутация: нет
Всего: 0



Цитата(БелАмор @ 18.1.2011,  21:36)
Цитата(KaraKum @  18.1.2011,  19:43 Найти цитируемый пост)
А там где эта переменная используется нужно писать перед началом её использования:
extern int x;

Это нужно писать в h-файле.

Можно вполне обойтись и без .h файла. Например так (два .cpp файла):
Код

#include <iostream>
#include <conio.h>

int x = 5;
void f ();
int main()
{
    std::cout << x << std::endl;
    f();
}

Код

#include <iostream>
extern int x;
void f ()
{
    std::cout << x << std::endl;
}

PM MAIL   Вверх
mes
Дата 18.1.2011, 22:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(Alchimik @  18.1.2011,  20:52 Найти цитируемый пост)
Можно вполне обойтись и без .h файла. Например так (два .cpp файла):

  smile , только маленький вопросик.. если  int x сделать константным, то не слинкуется.. как исправить то ?



--------------------
PM MAIL WWW   Вверх
Alchimik
Дата 18.1.2011, 22:24 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 1.12.2009

Репутация: нет
Всего: 0



Цитата(mes @ 18.1.2011,  22:04)
Цитата(Alchimik @  18.1.2011,  20:52 Найти цитируемый пост)
Можно вполне обойтись и без .h файла. Например так (два .cpp файла):

  smile , только маленький вопросик.. если  int x сделать константным, то не слинкуется.. как исправить то ?

Область видимости переменной объявленной со спецификатором const ограничена файлом. Это свойство позволяет определять переменные со спецификатором const в заголовочных файлах, при этом для каждого файла, подключающего данный заголовочный файл будет создана собственная копия константы.

Или надо написать extern const int x = 5;

Это сообщение отредактировал(а) Alchimik - 18.1.2011, 22:32
PM MAIL   Вверх
БелАмор
Дата 18.1.2011, 22:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 209
Регистрация: 10.6.2010
Где: Россия

Репутация: нет
Всего: 17



Цитата(Alchimik @  18.1.2011,  21:52 Найти цитируемый пост)
Можно вполне обойтись и без .h файла.

Можно, но не нужно... Если вы напишите в десяти cpp-файлах "extern int x", а потом решите изменить тип переменной? Зачем изобретать себе лишнюю головную боль? И в конце концов - это просто некрасиво...
PM   Вверх
mes
Дата 19.1.2011, 13:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(Alchimik @  18.1.2011,  21:24 Найти цитируемый пост)
Или надо написать extern const int x = 5;

 smile

Добавлено через 1 минуту и 51 секунду
Цитата(Alchimik @  18.1.2011,  21:24 Найти цитируемый пост)
Область видимости переменной объявленной со спецификатором const ограничена файлом. 

только "область видимости" кое что другое.. 
smile


--------------------
PM MAIL WWW   Вверх
Alchimik
Дата 19.1.2011, 16:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 1.12.2009

Репутация: нет
Всего: 0



Цитата(mes @  19.1.2011,  13:37 Найти цитируемый пост)
только "область видимости" кое что другое.. 

Я так понимаю что облать видимости - это некоторое пространство, такое, что переменная объявленная в нем доступна от своего объявления и до конца области. Или это не так?

PM MAIL   Вверх
mes
Дата 19.1.2011, 16:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(Alchimik @  19.1.2011,  15:21 Найти цитируемый пост)
Я так понимаю что облать видимости - это некоторое пространство, такое, что переменная объявленная в нем доступна от своего объявления и до конца области.

да..  но глобальные константы из примера не линкуются по другому поводу.. smile

Добавлено через 59 секунд
видимость что у константной, что у обычной переменной одна и та же...



--------------------
PM MAIL WWW   Вверх
Alchimik
Дата 19.1.2011, 16:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 1.12.2009

Репутация: нет
Всего: 0



Цитата(mes @  19.1.2011,  16:38 Найти цитируемый пост)
видимость что у константной, что у обычной переменной одна и та же...

Цитата

"неконстантная переменная, определённая в глобальной области видимости, доступна на протяжении всей программы."
..
"В отличие от других переменных, если противное не указано явно, объявленные в глобальной области видимости константы локальны для файла, в котором они определены"

Цитата из С++ Primer. Липпман, 80 стр.
PM MAIL   Вверх
mes
Дата 19.1.2011, 16:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(Alchimik @  19.1.2011,  15:51 Найти цитируемый пост)
Цитата из С++ Primer. Липпман, 80 стр. 

ну и где тут сказано, что у них иная область видимости ? smile smile





--------------------
PM MAIL WWW   Вверх
Alchimik
Дата 19.1.2011, 17:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 1.12.2009

Репутация: нет
Всего: 0



Цитата(mes @  19.1.2011,  16:57 Найти цитируемый пост)
ну и где тут сказано, что у них иная область видимости ?  

Я может что то путаю в терминалогии, но по мойму переменная без const объявленная в гловальной области видимости принадлежит глобальной области видимости, а переменная с const объявленная в глоальной области видимости ей не принадлежит, так как её облать видимости ограничена файлом.

Или же надо понимать так: они обе принадлежат глобальной области видимости, но константа при этом локальна для файла. 
PM MAIL   Вверх
mes
Дата 19.1.2011, 21:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(Alchimik @  19.1.2011,  16:07 Найти цитируемый пост)
Или же надо понимать так: они обе принадлежат глобальной области видимости, но константа при этом локальна для файла. 

ага близко..  
области видимости принадлежит объявление, но не определение.. а локально (т.е имеет внутренее связывание) как раз определение.. 
в общем вам сюда http://www.cyberguru.ru/programming/cpp/cp...up2-page52.html

P.S. что считается файлом в вышеприведенном контексте  ?

Добавлено через 33 секунды
(если конечно не надо своими вопросами smile )


--------------------
PM MAIL WWW   Вверх
Alchimik
Дата 20.1.2011, 11:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 18
Регистрация: 1.12.2009

Репутация: нет
Всего: 0



Цитата(mes @  19.1.2011,  21:43 Найти цитируемый пост)
P.S. что считается файлом в вышеприведенном контексте  ?

Помойму под "файлом" подразумевается просто файл, в котором объявлена переменная   smile 


Цитата(mes @  19.1.2011,  21:43 Найти цитируемый пост)
(если конечно не надо своими вопросами  )

Нет конечно, спасибо вам за помощь и за то что указываете мне на мои ошибки. Хоть и учусь на факультете кибернетики, а изучать программирование проходится самому, по книгам. Поэтому ваши указания на неправильно понятые мною места особенно полезны для меня. Спасибо вам  smile 
PM MAIL   Вверх
mes
Дата 20.1.2011, 15:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 79
Всего: 250



Цитата(Alchimik @  19.1.2011,  15:51 Найти цитируемый пост)
 локальны для файла, в котором они определены

под файлом подразумевается единица трансляции - т.е. .cpp файл со всеми включениями.. 



--------------------
PM MAIL WWW   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0836 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.