Отправляет email-рассылки с помощью сервиса Sendsay

Программирование. Форум !!!

error LNK2005: VC++ 6.0

Glad to greet!

Когда-то уже писал о данной проблеме, но сейчас снова выплыла.
Есть хидер (xxx.h), в котором определяется переменная и значение
(int i=1) или функция и реализация. Затем они include-ятся в другом
файле (yyy.h), который в свою очередь include-ится в 3-ем (zzz.h).
На этапе линковки вылезает такое вот сообщение:
"yyy.obj : error LNK2005: "int i" already defined in zzz.obj"

Естественно, в ххх.h стоят #ifdef-ы, так что подключение происходит
лишь единожды. Объявлять переменную как static не подходит,
поскольку в таком случае у каждого подключившего хранится своя
копия переменной, а не одна на всех (что меня несколько озадачило).
При указании /FORCE:MULTIPLE линкеру лезут warning-и, которые
pragma-ой не отключить, да и явно должен быть какой-то куда более
простой способ, однако моих поверхностных знаний с++ тут явно
недостаточно. Как с этим побороться? Заранее спасибо.

Alles Gute!

...In Code We Trust...

Ответить   Wed, 18 May 2005 18:07:50 +0400 (#370348)

 

Ответы:

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

Номер выпуска : 4506
Возраст листа : 607 (дней)
Количество подписчиков : 516
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/370402
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Fri, 20 May 2005 02:13:02 +0400 (#370402)

 

Я чего-то не пойму. Если это у тебя заголовки, какого лешего они у тебя
самостоятельно компилятся?? Как это из yyy.h и zzz.h получаются yyy.obj и
zzz.obj? Для начала ответь на этот вопрос, остальные проблемы, возможно,
сами уйдут.

--
С уважением, boroda
mailto:boroden***@s*****.ru

Номер выпуска : 4507
Возраст листа : 607 (дней)
Количество подписчиков : 515
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/370560
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Шматко А.А. Fri, 20 May 2005 10:11:22 +0400 (#370560)

 

Доброй поры суток...

Я вообще-то пропустил начало и потому могу быть не прав...

попробуй делать так:
все классы и переменные, которые тебе нужно использовать, создавай в
каком-нить 123.h
а дальше, в программе делай вызов extern

extern CString str;

Павел a.k.a BOER mailto:bo***@p*****.net

Номер выпуска : 4509
Возраст листа : 608 (дней)
Количество подписчиков : 515
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/371504
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Ищук Павел Sat, 21 May 2005 15:47:12 +0300 (#371504)

 

Glad to greet, Ищук!

You seem to have written (Saturday, May 21, 2005):

Не подходит, не хочется делать хидер, в котором будут десятки
классов, переменных и пр. Тем более, что часто надо использовать в
разных приложениях одни и те же классы/функции.

Alles Gute!

...In Code We Trust...

Ответить   Thu, 26 May 2005 22:06:15 +0400 (#374278)

 

Glad to greet, Шматко!

You seem to have written (Friday, May 20, 2005):

и

В таком случае расскажи как должно быть и как сделать по-людски.
Мне-то казалось, что всё нормально - из объектника взять
скомпилированный код, определить смещения, бухнуть в ехе и всё (может
это связано с использованием precompiled headers?).

Alles Gute!

...In Code We Trust...

Ответить   Thu, 26 May 2005 22:09:21 +0400 (#374296)

 

Здравствуйте !


Кстати, зачем в h писать реализацию ?
Нормально, это когда в h только декларации находятся, а реализации -
в c/cpp (хотя в ATL/WTL именно в h).

Можно (если уж очень хочется в h-нике), писать так:

#if !defined _CHTO_TO
#deine _CHTO_TO

int i = 1;

#endif


Тут главное понять как работает директива include.
Можно сказать, что она просто содержимое указанного файла
_полностью_ вставляет вместо себя.
А потом все это компилится.

То есть например.

Файл i1.h:
int a1 = 0;

Файл i2.h:
int a2 = 0;

Файл i3.h:
int a3 = 0;

Файл c.cpp:

...
#include "i1.h"
#include "i2.h"
#include "i3.h"
...

скомпилится так, как если бы в нем просто написать

...
int a1 = 0;
int a2 = 0;
int a3 = 0;
...


Во тут то и прикол.
Если например написать в c.cpp:

#include "i1.h"
#include "i1.h"

вылетит ошибка, потому что это будет эквивалентно:
int a1 = 0;
int a1 = 0;

А это - двойное обьявление переменной.





По людски - в h-ники вынести объявления (декларации классов, прототипы
функций).


Зачем вообще нужны h-файлы ?

ПРОСТО ЧТОБЫ НЕ ПИСАТЬ ОДНО И ТО ЖЕ МНОГО РАЗ.


То есть если создать 2 cpp файла и написать:

файл c1.cpp:

function a(int n)
{
...
}


файл c2.cpp:

extern function a(int n);

function aaa(int n)
{
a(n);
}


то все будет OK.


Но представь, что есть 100 функций, которые используются в 50 cpp файлах.
Можно описывать в _каждом_ cpp файле нужные прототипы функций, а можно -
в одном h файле описать все прототипы прототипы и во все cpp этот
h подключать.


--
С уважением, Вахтуров Виктор.

Номер выпуска : 4519
Возраст листа : 614 (дней)
Количество подписчиков : 523
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/374399
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Fri, 27 May 2005 02:46:57 +0400 (#374399)

 

Glad to greet, Victor!

You seem to have written (Friday, May 27, 2005):

Для скорости (при отладке, постепенном добавлении/удалении методов
или каких-то параметров в класс), чтобы не вносить изменения дважды.

Да, но я туда перенесу, когда класс будет завершен, а там может и в
lib.




Ессно, в h стоят (вот так:
#ifndef _xxx_
#define _xxx_
...
#endif
).
Но еррора всё равно лезет 8\.

Да знаю я про препроцессор и include, в том-то и дело. Потому-то и
удивляет проблема...

Так и делаю, но на этапе модификации/"допроектирования" удобно когда
реализация прямо под декларацией.

Есть много классов и ещё они все друг друга используют
("зацикливаний" нет), а потом все подключаются в главный файл.




В том-то и дело, что не хочется каждый раз писать extern для каждой
функции/переменной, а просто подключить h и спокойно использовать.

Alles Gute!

...In Code We Trust...

Ответить   Fri, 3 Jun 2005 23:52:34 +0400 (#378944)

 

Здравствуйте !


Можно попробовать дефайнами окружать реализации ?
То есть:

#ifndef _xxx_
#define _xxx_

class aaa
{
void a0();
void a1();
}

#ifndef _aaa_
#define _aaa_
void aaa::a0();
void aaa::a1();
#endif // aaa

#endif


Ну да... В принципе, дело привычки, наверно.

--
С уважением, Вахтуров Виктор.

Номер выпуска : 4557
Возраст листа : 622 (дней)
Количество подписчиков : 524
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/378958
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Sat, 4 Jun 2005 01:02:51 +0400 (#378958)

 

Ну, ВВ тебе уже всё объяснил. От себя добавлю следующее.

1. Заголовки - это (в частности) средство декларации интерфейсов. В простом
plain-C иначе декларировать интерфейс было просто не возможно. C++ эту
возможность унаследовал в силу простоты и удобства. По мне, так методы
декларации интерфейсов Turbo/Borland Pascal и Modula-2 куда как более
неудобны, а в Delphi вообще доведены до маразматической сложности.

2. Так как заголовки описывают интерфейс чего-то там (например, stdio.h
описывает интерфейс стандартной подсистемы ввода-вывода в plain-C, vector -
интерфейс класса vector<> в C++, locale - интерфейс средств локализации и
поддержки национально- и культурно- зависимых характеристик операционного
окружения программы, итд), то реализации в них быть не должно. Исключение
делается только для информации, без которой невозможно обойтись в принципе -

это подставляемые (inline) функции и шаблоны, так как они нужны прямо здесь
и сейчас. И то для шаблонов - это скорее от лени поставщиков средств
разработки, чем по необходимости. Export templates им видите ли напряжно
поддержать.

3. Любое что-нибудь external linkage, появляющееся в заголовке (а
подставляемые функции и шаблоны как раз в большинстве случаев к ним могут не

относиться), это потенциальный источник проблем при сборке, как ты уже
убедился и как это прояснил ВВ. НЕ ДОЛЖНО быть реализации интерфесов в
заголовках. Не для этого они предназначены. Короче, если в процессе
компиляции чисто заголовка компилятор порождает ненулевой объём объектного
кода (не путай с нулевым размером объектного файла), то этот заголовок
неправильный. Реализация должна быть в отдельной единице компиляции. Даже
если она состоит всего лишь из одного определения `int i=0;` Исключения
"разрешены" стандартом только для константных r-value, например `const int
i=0`. Но уже для `const coolClass myClass(someExpression)` это будет
неверно, ибо это l-value.

4. Имеет смысл создавать заголовки не только для экономии размера кода. Даже

если заголовок будет использован в проекте всего один раз, всё равно он
решает свою задачу по декларации интерфейса. Действительно, ведь новый класс

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

5. Заголовки не имеют самостоятельного применения. Окромя быть прочитанными
программистом, "по диагонали", возможно. Заголовки включаются в единицу
компиляции, как составные её части, снабжая компилятор объявлениями.
Реализация всего этого потом и позже подлинкуется при сборке.

Ещё вопросы?

--
С уважением, boroda
mailto:boroden***@s*****.ru

Номер выпуска : 4521
Возраст листа : 614 (дней)
Количество подписчиков : 524
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/374490
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Шматко А.А. Fri, 27 May 2005 09:42:22 +0400 (#374490)

 

Приветствую вас, Шматко А.А.!

27.05.2005 10:42 вы писали:

-

EDG потратили на реализацию export templates 1.5 года. Причем, насколько
мне известно, далеко не все так гладко при их использовании, как
хотелось бы. Комитет отклонил предложение Саттера об исключении
механизма раздельной компиляции шаблонов из следующей редакции
стандарта, но, как мне кажется, в ближайшие годы ситуация не изменится к
лучшему :( Заказная инстанциация иногда спасает, но в целом...

Ответить   Sat, 28 May 2005 21:00:19 +0500 (#375315)

 

С EDG ситуация понятна - они-то frond-end-ы выпускают, и в идеале -
переносимые. Или я ошибаюсь? Но конкретные реализации-то не страдают от
тисков многоплатформенности. Та же MicroSoft за 7 лет - от VC6 до VC7.1 -
могла бы построить канал обратной связи от линкера к компилятору... Это ж
простейший способ поддержки export templates. Впрочем, EDG используется в
Intel C++ Compiler, однако ж и там нет их поддержки.
Впрочем, мне по барабану вынужденная открытось исходного кода моих
шаблонов. Мне не по барабану публичность реализации. "Чёрный ящик" на то и
"чёрный ящик", чтоб реализация оставалась скрытой, дабы не смущать его
пользователя.

Я даже и не слышал, что над export templates нависали тучи... 8-{

--
С уважением, boroda
mailto:boroden***@s*****.ru

Номер выпуска : 4528
Возраст листа : 617 (дней)
Количество подписчиков : 521
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/376262
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Шматко А.А. Mon, 30 May 2005 16:37:30 +0400 (#376262)

 

Приветствую вас, Шматко А.А.!

30.05.2005 17:37 вы писали:

С 8-го есть. Если ухитрюсь поставить ICC 8.1 на свой Slackware (или
найти поддерживаемый Интелом дистр), попробую поиграться.
CBuilder X (если Borland не убил вконец свою ветку компиляторов C++)
тоже EDG-based и тоже поддерживает export.

Я узнал из дополнения Страуструпа к японскому переводу D&E 2005 года:
http://www.research.att.com/~bs/DnE2005.pdf
Интересное чтиво.

P.S. Не знаю, работал ли Саттер в 2003 году в MS, но при желании можно
увидеть в этом "руку" дженериков и C++/CLI :)

Ответить   Mon, 30 May 2005 18:43:23 +0500 (#376288)

 

Поискал поддержку в 8.0 Не нашёл, к сожалению. Может имелся в виду именно
8.1?

Наконец-то Borland - или как так её на этой неделе - признала свою
несостоятельность в производстве C++ компиляторов! Стыдно сказать, но код,
нормально компилирующийся в VC6 - это который вышел ещё до ратификации
нынешнего стандарта! - начисто отвергается последним Builder-ом, который
не -X. А там всего-то было чуть-чуть метапрограммирования на шаблонах.

--
С уважением, boroda

Номер выпуска : 4552
Возраст листа : 621 (дней)
Количество подписчиков : 524
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/378740
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Шматко А.А. Fri, 3 Jun 2005 16:31:40 +0400 (#378740)

 

Glad to greet, Шматко!

You seem to have written (Friday, May 27, 2005):

Так там же всё проектировалось под процедурный стиль, было вполне
логично (по крайней мере, мне так всегда казалось).

Зато помню, хорошо переводился код с чистого тп на delphi.
Но не во флейме дело ;)

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

не

Согласен, хотел схалтурить...

При относительно большом объеме кода для меня это ОЧЕНЬ существенно -
когда можно смотреть только public и тут же комменты (кста, а есть
что-то типа javadoc для С++?).

"Что делать?"
То бишь, единственный путь скидывать реализацию в *.спп?

Alles Gute!

...In Code We Trust...

Ответить   Sat, 4 Jun 2005 00:05:00 +0400 (#378952)

 

:) Знакомо дело... Не халтурь - привыкнешь

Есть. И не мало. Но меня не интересовали, поэтому за ссылочками не ко мне.

По крайней мере, так не наглючишь...
А вообще, не видя твоих исходников, сложно решить, из-за чего у тебя
проблемы. Счас поднял весь тред, всё равно информации мало. Но судя по тому,

как ты это описываешь - это твои глюки с неправильно реализованными
директивами условной компиляции. Или реализованной не для всех заголовков.

--
С уважением, boroda

Номер выпуска : 4562
Возраст листа : 624 (дней)
Количество подписчиков : 527
Адрес в архиве : http://subscribe.ru/archive/comp.soft.prog.prog/msg/379537
Получить правила : mailto:comp.soft.prog.prog-rules@subscribe.ru
Формат "дайджест" : mailto:comp.soft.prog.prog-digest@subscribe.ru
Формат "каждое письмо" : mailto:comp.soft.prog.prog-normal@subscribe.ru
Формат "читать с веба" : mailto:comp.soft.prog.prog-webonly@subscribe.ru

Ответить   Шматко А.А. Mon, 6 Jun 2005 11:55:54 +0400 (#379537)