Здравствуйте, Erop, Вы писали:
LVV>>А линкер вот причем. Определение класса Array попадает и в файл с определением методов TArray.cpp, и в файл с функцией main. То есть при сборке — две штуки должно обнаруживаться. E>А в каком виде, по твоему, оно попадает в объектный файл, чтобы как-то повлиять на сборку? Я так понимаю, речь идёт о вполне конкретном компиляторе, кстати...
Не, не стыдно... Стыдно не знать и лепить всякую лабуду...
А я человек любознательный. Хотя иногда бывает ступор. Но это тока от недосыпа...
Кажись до меня дошло... Спасибо...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, LaptevVV, Вы писали:
LVV>А линкер вот причем. Определение класса Array попадает и в файл с определением методов TArray.cpp, и в файл с функцией main. То есть при сборке — две штуки должно обнаруживаться.
А в каком виде, по твоему, оно попадает в объектный файл, чтобы как-то повлиять на сборку? Я так понимаю, речь идёт о вполне конкретном компиляторе, кстати...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, LaptevVV, Вы писали:
LVV>Работаю в Visual C++.NET 2005 LVV>Делаю простейший пример:
Причем тут вообще линкер? В первом случае у тебя TArray.h только один раз включается в каждый .cpp файл, а во втором случае он включается два раза в TFlex.cpp и в main.cpp: первый раз сам по себе, второй через TFlex.h. Вот компилятор и начинает ругаться, что у тебя по 2 раза все определено.
А TFlex.h без прагмы работает, так как он включается только по одному разу в TFlex.cpp и в main.cpp.
LVV>Такое чувство, что один раз система по умолчанию сама разруливает, а последующие включения — уже нет.
И не надейся, начинай каждый хидер с #pragma once )
Здравствуйте, Were, Вы писали:
W>Причем тут вообще линкер? В первом случае у тебя TArray.h только один раз включается в каждый .cpp файл, а во втором случае он включается два раза в TFlex.cpp и в main.cpp: первый раз сам по себе, второй через TFlex.h. Вот компилятор и начинает ругаться, что у тебя по 2 раза все определено. W>А TFlex.h без прагмы работает, так как он включается только по одному разу в TFlex.cpp и в main.cpp.
Дык при трансляции, естественно, никаких сообщений не должно выдаваться. Оно и не выдается.
А линкер вот причем. Определение класса Array попадает и в файл с определением методов TArray.cpp, и в файл с функцией main. То есть при сборке — две штуки должно обнаруживаться.
Обычно на повторное определение линкер выдает сообщение. А здесь — не выдает. W>И не надейся, начинай каждый хидер с #pragma once )
Предпочитаю стража.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, LaptevVV, Вы писали:
LVV>Здравствуйте, Were, Вы писали:
W>>Причем тут вообще линкер? В первом случае у тебя TArray.h только один раз включается в каждый .cpp файл, а во втором случае он включается два раза в TFlex.cpp и в main.cpp: первый раз сам по себе, второй через TFlex.h. Вот компилятор и начинает ругаться, что у тебя по 2 раза все определено. W>>А TFlex.h без прагмы работает, так как он включается только по одному разу в TFlex.cpp и в main.cpp. LVV>Дык при трансляции, естественно, никаких сообщений не должно выдаваться. Оно и не выдается. LVV>А линкер вот причем. Определение класса Array попадает и в файл с определением методов TArray.cpp, и в файл с функцией main. То есть при сборке — две штуки должно обнаруживаться.
Насколько я понимаю, определение класса никуда не попадает, оно только компилятору нужно И как бы здесь помог страж? Что со стражем, что без, после препроцессора TArray.h попадает в оба .cpp
Работаю в Visual C++.NET 2005
Делаю простейший пример:
// -- файл TArray.h ---------------------------#include <iostream>
using namespace std;
class Array // интерфейс: определение класса Array
{ /* ... */ };
// -- файл TArray.cpp -------------------------#include"TArray.h"// подключение интерфейса#include <iostream>
using namespace std;
Array::Array( Array::size_type size, Array::value_type k )
{ /* ... */ }
// внешние определения остальных методов
// -- файл main.cpp ---------------------------#include"TArray.h"// подключение интерфейса#include <iostream>
using namespace std;
int main()
{ /* ... */ };
Обратите внимание, ни pragmы, ни стража в заголовке TArray.h не прописано. Тем не менее, все транслируется и собирается и работает корректно.
В проекте это три отдельных файла. По идее линкер должен выдать повторное определение. Но не дает
Чуть усложняю пример:
// -- файл TArray.h ---------------------------#ifndef _ARRAY_ // страж определен?#define _ARRAY_ // если нет - определяем#include <iostream>
using namespace std;
class Array // интерфейс: определение класса Array
{ /* ... */ };
#endif// конец #ifndef
// -- файл TArray.cpp -------------------------#include"TArray.h"// подключение интерфейса#include <iostream>
using namespace std;
Array::Array( Array::size_type size, Array::value_type k )
{ /* ... */ }
// внешние определения остальных методов
// --------------------------------------------
// -- файл TFlex.h ----------------------------
//#pragma once // компилировать один раз#include"TArray.h"class Flex: public Array
{ /* ... */ };
#endif// конец #ifndef
// -- файл TFlex.cpp -------------------------#include"TArray.h"#include"TFlex.h"// реализация конструкторов
Flex::Flex():Array(minSize), Count() {}
// внешние определения остальных методов
// --------------------------------------------
// -- файл main.cpp ---------------------------#include"TArray.h"// подключение интерфейса Array#include “TFlex.h” // подключение интерфейса Flex#include <iostream>
using namespace std;
int main()
{ /* ... */ };
Я закомментировал прагму во TFlex.h, поскольку и так компилировалось. В этом варианте потребовалось прописать стража в TArray.h, так как линкер выдал сообщение о повторном определении.
Такое чувство, что один раз система по умолчанию сама разруливает, а последующие включения — уже нет.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
3.2/5
There can be more than one definition of a class type (clause 9), enumeration type (7.2), ... in a program provided that each
definition appears in a different translation unit, and provided the definitions satisfy the following requirements.
Далее идет перечисление всех требований, и еще далее:
If the definitions of D do not satisfy these requirements, then the behavior is undefined.
Возможно, что твой первый пример удовлетворяет всем требованиям, и множественная декларация класса не является ошибкой. А возможно, что отсутствие диагностики — одно из проявлений UB
Так что про стражей (прагмы) забывать не нужно — а то себе дороже выйдет...
Здравствуйте, LaptevVV, Вы писали:
LVV>Здравствуйте, Were, Вы писали:
W>>Причем тут вообще линкер? В первом случае у тебя TArray.h только один раз включается в каждый .cpp файл, а во втором случае он включается два раза в TFlex.cpp и в main.cpp: первый раз сам по себе, второй через TFlex.h. Вот компилятор и начинает ругаться, что у тебя по 2 раза все определено. W>>А TFlex.h без прагмы работает, так как он включается только по одному разу в TFlex.cpp и в main.cpp. LVV>Дык при трансляции, естественно, никаких сообщений не должно выдаваться. Оно и не выдается. LVV>А линкер вот причем. Определение класса Array попадает и в файл с определением методов TArray.cpp, и в файл с функцией main. То есть при сборке — две штуки должно обнаруживаться.
Так у тебя в TArray.h определение или объявление класса? Если только объявление, то линкер все-таки не причем, а если определение, то и в первом случае он будет ругаться. Может приведешь минимальный пример, демонстрирующий, что именно, по-твоему, разруливает ликер?
LVV>Обычно на повторное определение линкер выдает сообщение. А здесь — не выдает. W>>И не надейся, начинай каждый хидер с #pragma once ) LVV>Предпочитаю стража.
The last good thing written in C was Franz Schubert's Symphony No. 9.
Здравствуйте, LaptevVV, Вы писали:
LVV>Здравствуйте, Were, Вы писали:
LVV>А линкер вот причем. Определение класса Array попадает и в файл с определением методов TArray.cpp, и в файл с функцией main. То есть при сборке — две штуки должно обнаруживаться.
По-моему ты путаешь declaration и implementation.
Объявление класса — это все лишь объявление типа, линкеру абсолютно все равно, сколько раз класс был объявлен. Вот если бы ты два раза реализовал какой-нибудь метод класса, тогда бы уж он оторвался по полной
Здравствуйте, Were, Вы писали:
W>Здравствуйте, LaptevVV, Вы писали:
LVV>>Здравствуйте, Were, Вы писали:
LVV>>А линкер вот причем. Определение класса Array попадает и в файл с определением методов TArray.cpp, и в файл с функцией main. То есть при сборке — две штуки должно обнаруживаться. W>По-моему ты путаешь declaration и implementation. W>Объявление класса — это все лишь объявление типа, линкеру абсолютно все равно, сколько раз класс был объявлен. Вот если бы ты два раза реализовал какой-нибудь метод класса, тогда бы уж он оторвался по полной
Точно! Declaration же блин!
Спасибо.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Здравствуйте, LaptevVV, Вы писали:
LVV>Кажись до меня дошло... Спасибо...
Для "спасибо" тут есть кнопки.
А тормоза -- это да, у всех бывают Вот у меня например...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, alexeiz, Вы писали:
A>Здравствуйте, jazzer, Вы писали:
J>>Ох, завалишь ты сессию, придется на пересдачу
A>За "using namespace std" в хедере сразу незачет. Чему студентов учите, спрашивается?
Да, мне это тоже в глаза сразу бросилось.
Но, может, для студентов это и нормально...
Хотя, конечно, хорошие привычки лучше сразу прививать
Здравствуйте, alexeiz, Вы писали:
J>>Ох, завалишь ты сессию, придется на пересдачу A>За "using namespace std" в хедере сразу незачет. Чему студентов учите, спрашивается?
Да убрал уже без напоминаний...
Немного отоспался — и убрал...
И по поводу остального — как-то в подсознухе устаканилось...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!