Не нужен страж?
От: LaptevVV Россия  
Дата: 03.06.08 07:36
Оценка:
Работаю в 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, так как линкер выдал сообщение о повторном определении.

Такое чувство, что один раз система по умолчанию сама разруливает, а последующие включения — уже нет.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
раздельная трансляция
Re: Не нужен страж?
От: Bell Россия  
Дата: 03.06.08 07:55
Оценка:
Здравствуйте, LaptevVV, Вы писали:

Нужен, нужен:

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

Так что про стражей (прагмы) забывать не нужно — а то себе дороже выйдет...
Любите книгу — источник знаний (с) М.Горький
Re: Не нужен страж?
От: Were  
Дата: 03.06.08 08:09
Оценка: 1 (1)
Здравствуйте, 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 )
Re[2]: Не нужен страж?
От: LaptevVV Россия  
Дата: 03.06.08 10:35
Оценка: :)
Здравствуйте, 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 )
Предпочитаю стража.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
раздельная компиляция
Re[3]: Не нужен страж?
От: crable США  
Дата: 03.06.08 11:12
Оценка:
Здравствуйте, 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.
Re[3]: Стыдно, Лаптев, а ещё книжки пишите :(
От: Erop Россия  
Дата: 03.06.08 11:13
Оценка: 18 (1)
Здравствуйте, LaptevVV, Вы писали:

LVV>А линкер вот причем. Определение класса Array попадает и в файл с определением методов TArray.cpp, и в файл с функцией main. То есть при сборке — две штуки должно обнаруживаться.

А в каком виде, по твоему, оно попадает в объектный файл, чтобы как-то повлиять на сборку? Я так понимаю, речь идёт о вполне конкретном компиляторе, кстати...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: Не нужен страж?
От: Fwiffo Россия  
Дата: 03.06.08 11:18
Оценка: +1
Здравствуйте, 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
Re[3]: Не нужен страж?
От: Were  
Дата: 03.06.08 11:20
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>Здравствуйте, Were, Вы писали:


LVV>А линкер вот причем. Определение класса Array попадает и в файл с определением методов TArray.cpp, и в файл с функцией main. То есть при сборке — две штуки должно обнаруживаться.

По-моему ты путаешь declaration и implementation.
Объявление класса — это все лишь объявление типа, линкеру абсолютно все равно, сколько раз класс был объявлен. Вот если бы ты два раза реализовал какой-нибудь метод класса, тогда бы уж он оторвался по полной
Re[4]: Стыдно, Лаптев, а ещё книжки пишите :(
От: LaptevVV Россия  
Дата: 03.06.08 12:39
Оценка: +1 :)
Здравствуйте, Erop, Вы писали:

LVV>>А линкер вот причем. Определение класса Array попадает и в файл с определением методов TArray.cpp, и в файл с функцией main. То есть при сборке — две штуки должно обнаруживаться.

E>А в каком виде, по твоему, оно попадает в объектный файл, чтобы как-то повлиять на сборку? Я так понимаю, речь идёт о вполне конкретном компиляторе, кстати...
Не, не стыдно... Стыдно не знать и лепить всякую лабуду...
А я человек любознательный. Хотя иногда бывает ступор. Но это тока от недосыпа...
Кажись до меня дошло... Спасибо...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[4]: Не нужен страж?
От: LaptevVV Россия  
Дата: 03.06.08 12:41
Оценка:
Здравствуйте, Were, Вы писали:

W>Здравствуйте, LaptevVV, Вы писали:


LVV>>Здравствуйте, Were, Вы писали:


LVV>>А линкер вот причем. Определение класса Array попадает и в файл с определением методов TArray.cpp, и в файл с функцией main. То есть при сборке — две штуки должно обнаруживаться.

W>По-моему ты путаешь declaration и implementation.
W>Объявление класса — это все лишь объявление типа, линкеру абсолютно все равно, сколько раз класс был объявлен. Вот если бы ты два раза реализовал какой-нибудь метод класса, тогда бы уж он оторвался по полной
Точно! Declaration же блин!
Спасибо.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[5]: Стыдно, Лаптев, а ещё книжки пишите :(
От: Erop Россия  
Дата: 03.06.08 13:02
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>Кажись до меня дошло... Спасибо...

Для "спасибо" тут есть кнопки.
А тормоза -- это да, у всех бывают Вот у меня например...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[5]: Не нужен страж?
От: jazzer Россия Skype: enerjazzer
Дата: 04.06.08 05:32
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>Точно! Declaration же блин!

LVV>Спасибо.

Ох, завалишь ты сессию, придется на пересдачу

У класса есть и declaration, и definition. Первое (в виде class MyClass; ) — сколько угодно, второе (в виде class MyClass {...}; ) — только один раз.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[6]: Не нужен страж?
От: alexeiz  
Дата: 04.06.08 06:42
Оценка:
Здравствуйте, jazzer, Вы писали:

J>Ох, завалишь ты сессию, придется на пересдачу


За "using namespace std" в хедере сразу незачет. Чему студентов учите, спрашивается?
Re[7]: Не нужен страж?
От: jazzer Россия Skype: enerjazzer
Дата: 04.06.08 06:50
Оценка:
Здравствуйте, alexeiz, Вы писали:

A>Здравствуйте, jazzer, Вы писали:


J>>Ох, завалишь ты сессию, придется на пересдачу


A>За "using namespace std" в хедере сразу незачет. Чему студентов учите, спрашивается?


Да, мне это тоже в глаза сразу бросилось.
Но, может, для студентов это и нормально...
Хотя, конечно, хорошие привычки лучше сразу прививать
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[7]: Не нужен страж?
От: LaptevVV Россия  
Дата: 04.06.08 07:12
Оценка:
Здравствуйте, alexeiz, Вы писали:

J>>Ох, завалишь ты сессию, придется на пересдачу

A>За "using namespace std" в хедере сразу незачет. Чему студентов учите, спрашивается?
Да убрал уже без напоминаний...
Немного отоспался — и убрал...
И по поводу остального — как-то в подсознухе устаканилось...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.