Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > немного о хеадерах


Автор: apook 20.9.2007, 12:29
Линкер выдает ошибку --
Error: _DAT defined in module main.cpp is duplicated in module dat.cpp

Суть такова:
В заголовочном файле dat.h есть структура DAT( там же заполняется ), в файле main.cpp включен файл dat.h и в dat.cpp тоже включен файл dat.h соответственно.
Ошибка потому что тип DAT обьявляется дважды, пачиму так smile? убедительная просьба разжувать
30 минут непоняток....

Автор: Daevaorn 20.9.2007, 12:33
Цитата(apook @  20.9.2007,  13:29 Найти цитируемый пост)
Линкер выдает ошибку --

если так, то:
Цитата(apook @  20.9.2007,  13:29 Найти цитируемый пост)
В заголовочном файле dat.h есть структура DAT( там же заполняется

заполнять её надо один раз. а у тебя получается два.

Автор: GrayCardinal 20.9.2007, 12:41
apook, 
Можно в файле main.cpp записать макрос (перед включением dat.h), к примеру :
#define MAIN_CPP
а в 
dat.h
#ifdef MAIN_CPP
(заполняем)
#else
(просто объявляем)
#endif

Автор: Fazil6 20.9.2007, 12:41
Цитата(apook @  20.9.2007,  12:29 Найти цитируемый пост)
Ошибка потому что тип DAT обьявляется дважды, пачиму так ? убедительная просьба разжувать30 минут непоняток....

ну чего тут непонятного? 2 раза одна и таже переменная определяется. Убирать ее определение из хедера

Автор: apook 20.9.2007, 12:46
Дело в том что она тока там и определяется(то бишь в хеадере)

так поправки:
структура такая --

struct 
{ 
    char Ы[ 3 ][ 1 ]; //идентификаторы
    int Г;
    } DAT={
    { "\x1", "\x1", "\x1" },
    { 25 }
    };

надо чтоб эта структура заполнялась только в файле dat.h и именно таким способом

Автор: GrayCardinal 20.9.2007, 12:49
apook, 
Именно таким способом не прокатит  smile

Добавлено через 1 минуту и 2 секунды
ЗЫ
и объявляется дважды НЕ ТИП, а ПЕРЕМЕННАЯ "DAT".

Автор: apook 20.9.2007, 13:06
Цитата(GrayCardinal @  20.9.2007,  12:49 Найти цитируемый пост)
и объявляется дважды НЕ ТИП, а ПЕРЕМЕННАЯ "DAT"
 Да это понятно там опечатка, но почему не прокатит не понятно я с этим не согласен, п о ч е м у у у???

Автор: Daevaorn 20.9.2007, 13:10
Цитата(apook @  20.9.2007,  14:06 Найти цитируемый пост)
п о ч е м у у у???

п о т о м у ч т о  в С + + т а к н е л ь з я! Определять переменные нужно в cpp файле, а чтобы они были видны не только там есть слово extern. читай доки!smile

Автор: apook 20.9.2007, 13:26
c extern все понятно
Цитата(Daevaorn @  20.9.2007,  13:10 Найти цитируемый пост)
Определять переменные нужно в cpp файле
 О, а как сделать? Хотелось заполнить сразу при обьявлении...

Автор: archimed7592 20.9.2007, 13:34
Цитата(apook @  20.9.2007,  13:06 Найти цитируемый пост)
Да это понятно там опечатка, но почему не прокатит не понятно я с этим не согласен, п о ч е м у у у???

Потому что header - это НЕ отдельный модуль, а всего лишь кусочек другого модуля. В твоём случае этот кусочек фигурирует аж в двух модулях(можешь с тем же успехом убрать include и руками скопировать содержимое своего хэдера в оба модуля), как и дважды фигурирует определение переменной DAT. Так понятно?

Автор: apook 20.9.2007, 13:59
Цитата(archimed7592 @  20.9.2007,  13:34 Найти цитируемый пост)
Так понятно?
 Но ведь дело в том что так и надо делать( по правильному, соответственно в main.cpp и функция int main() так что я не могу в этом модуле не включить и в нем dat.h так как из main я пользуюсь данными из структуры DAT), не прокатывает только заполнение структуры при ее обьявлении... я специально вытащил ее из класса только для того чтоб заполнять при обьявлении, в общем стоял перед выбором заполнять ее в конструкторе или таким способом, польстился чето на второй

Автор: GrayCardinal 20.9.2007, 14:39
Цитата

специально вытащил ее из класса только для того чтоб заполнять при обьявлении, в общем стоял 
перед выбором заполнять ее в конструкторе или таким способом, польстился чето на второй

Ыыыы. LOL.

Автор: Earnest 21.9.2007, 19:28
apook, так и заполняй себе при объявлении на здоровье. Только отдели мух от супа, т.е. объявление типа от объявления переменной. Первое - в хедер, второе - в cpp.
А не нравится - все претензии к Страуструпу - это он, гад, напридумал... 
А нет, это даже Керниган с прочими праотцами С...
smile  smile  smile 

Автор: archimed7592 21.9.2007, 19:38
apook, не парь мозги ни себе ни нам. Вот тебе пример(хотя их на форуме десятки):
Код

// dat.h
extern int x;

// dat.cpp
int x = 75; // определяем и инициализируем здесь(только в одном месте)

// module1.cpp
#include "dat.h"
void f1()
{ std::cout << x << std::end; }

// module2.cpp
#include "dat.h"
void f2()
{ std::clog << x << std::end; }

Если это не понятно, то советую обратиться к книге и постараться увидеть там нечто большее, чем "фигу".

Автор: apook 22.9.2007, 02:43
Цитата(archimed7592 @  21.9.2007,  19:38 Найти цитируемый пост)
// dat.hextern int x;// dat.cppint x = 75; // определяем и инициализируем здесь(только в одном месте)

Ну что-за пример! я б не додумался до такого
Заполнять при обьявлении имелось ввиду напр:
Код

char *str="Строка";

проделать сие в хеадере как я теперь понял нельзя....

Автор: archimed7592 22.9.2007, 08:06
Цитата(apook @  22.9.2007,  02:43 Найти цитируемый пост)
Заполнять при обьявлении имелось ввиду напр:

И чем твой пример отличается от int x = 75;? 0_o

Вообще говоря, тебе не плохо было бы узнать разницу между объявлением и определением. "Заполнять"(а точнее, инициализировать) при объявлении нельзя - так устроен язык С++.


Цитата(apook @  22.9.2007,  02:43 Найти цитируемый пост)
проделать сие в хеадере как я теперь понял нельзя....

В хэдере можно делать абсолютно всё, что можно делать в самом модуле(.cpp), но нужно осозновать возможные последствия содеянного.


Попробуй задаться для себя вопросом: в чём для тебя принципиальная разница "заполнения" в хэдере или модуле? Думаю, когда ответишь на него, все вопросы сразу отпадут.

Автор: apook 22.9.2007, 09:54
Цитата(archimed7592 @  22.9.2007,  08:06 Найти цитируемый пост)
Попробуй задаться для себя вопросом: в чём для тебя принципиальная разница "заполнения" в хэдере или модуле?
 Сложный вопрос. Думаю ответ:-"Так захотелось", почти подходит. Ну вобщем вопрос снят с повески дня! smile 

Автор: archimed7592 22.9.2007, 11:16
Цитата(apook @  22.9.2007,  09:54 Найти цитируемый пост)
Думаю ответ:-"Так захотелось"

Думаю ответ: хотелось инициализировать общую переменную в одном месте, но ты, почему-то выбрал для этого хэдер(таким образом сделав инициализацию во всех модулях, которые используют этот хэдер), вместо того, чтобы сделать инициализацию в одном из модулей или вообще в отдельном модуле.

Автор: apook 22.9.2007, 14:07
так, если уж разбитраться что подтолкнуло обьявить переменную в хеадере, то скажу что этому предшествовало, предупреждаю что все не очень серьезно. а дело было так, напоминаю что переменная является структурой и вполне вероятно, так как я не совсем ясно представляю всех нюансов достижения будущей программой поставленного результата, эта структура станет массивом структур.. Структура являлась членом некого класса, дойдя до написания конструктора которого я встал перед вопросом заполнения полей структуры( а заполняется она заранее известными данными) , их примерно 10 - 15(полей) т.е не много(чтоб начать плодить хеадеры с коими итак путанница) но и не мало чтоб это незаметно выглядело в конструкторе(строки типа 
Код
strcpy( p->DAT[ 0 ]. ident, "submamber_item_value" );
) и таких 15 x n. Ну просто представилось предпочтительнее заполнить структуру статически и не вспоминать о ее инициализации более ни где на протяжении всего кода.
Кстати уже инициализировал в конструкторе(временно), но однак так и останется.... 

Сейчас пришло на ум поиграться со значеничми по умолчанию и инициализировать типа статически, но опять же не все компиляторы поддерживают такую фишку в default constructor, есть-ли какие-нибудь соображения?? чты эт не очень серьезно так ка прога и так работть будет

Автор: Ln78 22.9.2007, 16:18
apook, при очень большом желании можно и зайца курить научить (вопрос зачем?). В твоём случае, один из вариантов может быть такой:
Код

#ifdef _DATA
#define _MOD
#define SET =
#define BRACE_L {
#define BRACE_R }
#define COMMA ,
#define INIT1(a) {(a)}
#define INIT2(a,b) {(a),(b)}
#define INIT3(a,b,c) {(a),(b),(c)}
#else
#define _MOD extern
#define INIT1(a) 
#define INIT2(a,b)
#define INIT3(a,b,c)
#define SET
#define BRACE_L 
#define BRACE_R 
#define COMMA 
#endif

_MOD struct S_DAT
{ 
    char S[ 3 ][ 2 ]; //идентификаторы
    int I;
} DAT SET BRACE_L 
      INIT3(("\x30"),("\x31"),("\x33")) COMMA 
      INIT1(25) 
  BRACE_R ;


В одном из *.cpp файлов нужно определить _DATA.

Автор: zkv 22.9.2007, 16:26
если инициализацией простой не обойтись, то можно сделать следущее:
(надеюсь правильно тебя понял)
Код

struct DATA
{
  const char *someField;
};

class CSome
{
  static DATA m_data;
  static bool  m_fDataIsConstructed;
public:
  CSome();
  static void ConstructData();
};

bool CSome::m_fDataIsConstructed = false;

CSome::CSome()
{
  if( !CSome::m_fDataIsConstructed )
    ConstructData();
}

void CSome::ConstructData()
{
  // initialize m_data here 
}

Автор: apook 22.9.2007, 16:41
Одной из причин было уменьшение строчек кода, хотяб иллюзия этого smile 
Спасибо за предложеннные  варианты.

Автор: zkv 22.9.2007, 16:55
Цитата(apook @  22.9.2007,  16:41 Найти цитируемый пост)
Одной из причин было уменьшение строчек кода

целью должна быть скорее прозрачность кода, а не количество строчек.  smile 

Автор: apook 28.9.2007, 13:24
как борться с тем что при включении хеадера значительно утяжеляется исполняемый файл, даже если (ради эксперемента) не вызывать ничего из этого файла ?

Автор: akizelokro 28.9.2007, 13:28
ради эксперимента попробовать не включать такой хедер smile 

Автор: apook 28.9.2007, 14:07
Мне почему-то хочется включить iostream.h

Хотя включив просто iostream.h файл не увеличивается, а если вызвать cout  то увеличивается с  4.67 kb  до 28.9 kb!!! smile
а файл string хватает просто включить и файл увеличивается до 70 kb smile smile smile ! И вобщем тогда тоже склоняюсь не включать таких файлов(как жаль)... 

Автор: archimed7592 28.9.2007, 14:33
Цитата(apook @  28.9.2007,  14:07 Найти цитируемый пост)
Мне почему-то хочется включить iostream.h 

Странные нынче программисты пошли...
no comments

Автор: apook 1.10.2007, 07:02
товарищ Уолтер Савич говорит что в cpp файле для хеадера следует писать
Код

//file somefile.cpp
#ifdef SOMEFILE_CPP
#define SOMEFILE_CPP

...

#endif

говорится так-же что при таком включении не надо передавать имя такого файла в параметре компилятора, а так же не надо включать его через include напр:  #include"somefile.cpp"
на практике это не работает. Работает так:
Код

//file somefile.cpp
#include"somefile.h"

и имя файла передается с пареметром компилятору
что-за ?

Автор: archimed7592 1.10.2007, 07:15
apook, ты сам то понял, что написал?

Автор: apook 1.10.2007, 08:24
Цитата(archimed7592 @  1.10.2007,  07:15 Найти цитируемый пост)
apook, ты сам то понял, что написал?
Да, ну если захотеть не понять то можно и не понять. Извиняюсь я не на экзамене и даже не на уроке чтоб  формулировать суперточно. Тебя смутила фраза
Цитата
в cpp файле для хеадера
, ну ты -же понял о чем я... че придераешься?

Автор: UnrealMan 1.10.2007, 08:41
Цитата(apook @  1.10.2007,  09:24 Найти цитируемый пост)
ну ты -же понял о чем я... 

Это вряд ли. Такой бред понять невозможно.

Автор: Fazil6 1.10.2007, 08:44
Цитата(apook @  1.10.2007,  08:24 Найти цитируемый пост)
Извиняюсь я не на экзамене и даже не на уроке чтоб  формулировать суперточно.

Извиняюсь, но тут тебе тоже никто не Буратино, чтобы догадываться о чем твоя галиматья и как ее коментировать...  

Автор: apook 1.10.2007, 08:56
а что именно не понятно то? я чесно не понял... smile 

Автор: akizelokro 1.10.2007, 09:11
Предположу, что достопочтенный товарищ Савич писал не

Код

#ifdef SOMEFILE_CPP
#define SOMEFILE_CPP

...

#endif


а

Код

#ifndef SOMEFILE_CPP
#define SOMEFILE_CPP

...

#endif


Также предпоожу, что (насколько я трудно тебя понял) он пытается показать как функции хедера (.hpp,.h файл) возложить на файл с расщирением .cpp. Если это даже близко не так, то мне вас не близко не понять

Автор: apook 1.10.2007, 09:32
да точно 
Код
#ifndef
 а не 
Код
#ifdef
 и оказалось что все в порядке.... Но все-же UnrealMan и archimed7592 где вы увидели бред, да еще такой степени что понять невозможно?  smile 

Автор: apook 1.10.2007, 09:49
Все разобраля! Действительно бредово получилось  smile  smile
Вот кусочек из примера Уолтера Савича
Код

#ifndef LIST_CPP
#define LIST_CPP
#include "list.h"  // Хотя в данном файле этого не требуется
                            // использование директивы #ifndef в файле list.h полезно
                            // для тех случаев, когда шаблон класса
                            // применяется в нескольких файлах программы. 
...
#endif

Смущает комментарий  "Хотя в данном файле этого не требуется" находящийся напротив включения #include "list.h", развивая мысль и убрав эту строку получаем ошибку .... has no been declared.
Запутал подлец с утра, а я напридумывал черти-че см мой вопрос выше

Автор: archimed7592 1.10.2007, 09:58
Цитата(apook @  1.10.2007,  08:24 Найти цитируемый пост)
Извиняюсь я не на экзамене и даже не на уроке чтоб  формулировать суперточно.

Ты на форуме, где ты должен формулировать свои вопросы достаточно точно, чтобы получить адекватные ответы.
Ты нафлудил 782 поста и так и не научился, ни вопросы задавать, ни мысли формулировать, ни программировать.
На месте модераторов я бы давно тебе влепил бы не одно предупреждение ибо такая халатность и отсутствие уважения к форумчанам(мы тебе чё, обязаны, что ль?) простительны только ньюбам.

Цитата(apook @  1.10.2007,  09:49 Найти цитируемый пост)
Вот кусочек из примера Уолтера Савича

Я его не читал, но если кусочек не сильно выдран из контекста, то могу лишь посоветовать Савичу пустить себе пулю в лоб, пока это не сделал кто-то другой.

Автор: apook 1.10.2007, 11:04
archimed7592 твои претензии выдраны из контекста
Цитата(archimed7592 @  1.10.2007,  09:58 Найти цитируемый пост)
мы тебе чё, обязаны, что ль?
Я ведь не к тебе именно обратился, а к тем кто непосчитает вопрос флудом и не против посоветовать.. 

Цитата(archimed7592 @  1.10.2007,  09:58 Найти цитируемый пост)
нафлудил 782 поста
 зачем так преувеличивать?

Цитата(archimed7592 @  1.10.2007,  09:58 Найти цитируемый пост)
 ни вопросы задавать, ни мысли формулировать, ни программировать.
 особенно третье, я никому не обязан научиться программировать тем более я занимаюсь этим (обучением) 2-ой год пошел...

Че-за крутизна, не нравлюсь не общайся


Автор: UnrealMan 1.10.2007, 12:22
Маленький совет: разберись с тем, что такое единица трансляции и правило одного определения, и узнай, что делают директивы include, ifndef, define, endif. Далее, если с логическим мышлением всё в порядке, тебе станет ясно, что и как надо делать.

Автор: archimed7592 1.10.2007, 14:24
Цитата(apook @  1.10.2007,  11:04 Найти цитируемый пост)
Че-за крутизна, не нравлюсь не общайся

"Крутизна" как раз таки исходит с твоей стороны:
Цитата(apook @  1.10.2007,  08:24 Найти цитируемый пост)
Извиняюсь я не на экзамене и даже не на уроке чтоб  формулировать суперточно.


А это:
Цитата(apook @  1.10.2007,  08:24 Найти цитируемый пост)
ну ты -же понял о чем я... че придераешься?

Если бы я понял, я бы наверное не спрашивал бы тебя понял ли ты сам.

Автор: JackYF 1.10.2007, 14:27
apook, согласен с UnrealMan и archimed7592. И от себя еще раз попрошу читабельно формулировать задачи, желательно используя знаки препинания в предложениях.

За код, приведенный тобой вначале, я бы послал автора штудировать Страуструпа и других хороших товарищей, так как в .cpp-файлах конструкция вида #ifndef... #define........#endif бессмысленна, потому что они и так транслируются один раз. Применима она как раз в хедерах, которые могут включаться не в один .cpp-файл.

Автор: zkv 1.10.2007, 16:03
apook, правда непонятно нифига, не заводись smile
Первый раз вижу защиту от двойного подключения в cpp-файле...

пропустил страницу обсуждения...

Автор: apook 1.10.2007, 17:22
Цитата(zkv @  1.10.2007,  16:03 Найти цитируемый пост)
Первый раз вижу защиту от двойного подключения в cpp-файле

Программирование на С++, 4 издание, Уолтер Савич, стр 649
специально нашел в инете электронный вариант прикрепил как-раз эту страницу. Надо поуглубленней изучит книгу тут говорят неплохой автор smile

Автор: Daevaorn 1.10.2007, 17:40
Цитата(apook @  1.10.2007,  18:22 Найти цитируемый пост)
Программирование на С++, 4 издание, Уолтер Савич, стр 649

Робски тоже "книги" пишет...

Автор: archimed7592 1.10.2007, 18:05
Цитата(apook @  1.10.2007,  17:22 Найти цитируемый пост)
Программирование на С++, 4 издание, Уолтер Савич, стр 649

А теперь разуй глаза и посмотри на 648 страницу. Это не модуль трансляции. Это обычный заголовочный файл с расширением .cpp
[не стал читать полностью, но, по всей видимости это пример того как можно "разделить" интерфейс от реализации в случае шаблонов]

Автор: apook 1.10.2007, 18:15
Цитата(archimed7592 @  1.10.2007,  18:05 Найти цитируемый пост)
Это не модуль трансляции
Впрочем я что-то подобное говорил в первом вопросе по этому поводу. Все-равно твоя реакция предвзята, че так сразу в штыки...

Автор: archimed7592 1.10.2007, 18:22
Цитата(apook @  1.10.2007,  18:15 Найти цитируемый пост)
Все-равно твоя реакция предвзята, че так сразу в штыки...

Ни хрена себе предвзята. 5 страниц флуду ни о чём.
Давай не будем обсуждать меня или тебя, а будем обсуждать твою проблему. Она исчерпана?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)