Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 20.07.2009, 20:36   #1
Роман Радер
Форумчанин
 
Аватар для Роман Радер
 
Регистрация: 16.12.2006
Сообщений: 859
По умолчанию заголовочный файл и файл исходного текста

Собственно, какая разница по сути? Есть куча файлов и среди них один единственный .cpp в котором main() и в него инклудятся все остальные. Если все равно все надо инклудить, какая тогда разница .h файл или .cpp или хоть .txt?
Сейчас я делаю так: у меня ОДИН cpp файл и куча .h. У других видел кучу cpp файлов, поэтому и спросил.
Роман Радер вне форума Ответить с цитированием
Старый 20.07.2009, 22:24   #2
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,065
По умолчанию

Цитата:
Сообщение от Роман Радер Посмотреть сообщение
Собственно, какая разница по сути? Есть куча файлов и среди них один единственный .cpp в котором main() и в него инклудятся все остальные. Если все равно все надо инклудить, какая тогда разница .h файл или .cpp или хоть .txt?
Да хоть "программа.моя" назовите. Главное - содержание, а не расширение, хотя таки принято заголовочные обзывать *.h или *.hpp и соответственно реализация в *.c (для Си) и *.cpp (для С++).
В заголовочных файлах должен быть только интерфейс (описание классов, функций, глобальных переменных,... исключение: шаблоны), а в cpp - реализация. Так же #include "Source.cpp" писать нихарашо)
Цитата:
Сообщение от Роман Радер Посмотреть сообщение
Сейчас я делаю так: у меня ОДИН cpp файл и куча .h. У других видел кучу cpp файлов, поэтому и спросил.
Главное - качество, а не количество.
pu4koff вне форума Ответить с цитированием
Старый 20.07.2009, 23:07   #3
ROD
Linux C++ Qt ARM
Старожил
 
Аватар для ROD
 
Регистрация: 30.11.2008
Сообщений: 3,030
По умолчанию

Цитата:
В заголовочных файлах должен быть только интерфейс (описание классов, функций, глобальных переменных,... исключение: шаблоны), а в cpp - реализация. Так же #include "Source.cpp" писать нихарашо)
Не понял. Если в .h только описание, а #include "Source.cpp писать не хорошо, где тогда описывать сами "тела функций" ?

К стати, а это хорошо или не очень, когда что-то инклудишь не в верху, а по мере возникновения необходимости в инклудивании чего-либо? (ну как с объявлением переменных)
Дилетант широкого профиля.

"Слова ничего не стоят - покажите мне код!" © Линус Торвальдс
ROD вне форума Ответить с цитированием
Старый 21.07.2009, 00:16   #4
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,065
По умолчанию

Цитата:
Сообщение от ROD Посмотреть сообщение
Не понял. Если в .h только описание, а #include "Source.cpp писать не хорошо, где тогда описывать сами "тела функций" ?
Тело функции - есть реализация, т.е. в *.cpp файлах им место. А инклюдить "сипипишки" и не надо, ибо они компилятору "автоматом" посылаются для обработки, а уже по инклюдам в них находятся хедеры.
Цитата:
Сообщение от ROD Посмотреть сообщение
К стати, а это хорошо или не очень, когда что-то инклудишь не в верху, а по мере возникновения необходимости в инклудивании чего-либо? (ну как с объявлением переменных)
Лучше вверху, чтобы легче просматривалась зависимость отдельных модулей программы. Появится так по невнимательности циклическая зависимость (а она может быть не прямая: a <-> b, а через пятое колено: a -> b -> c -> a) модулей и ищи свищи потом почему не линкуется программа, а поймешь почему, так ищи этот злочастный инклюд по всему коду...
pu4koff вне форума Ответить с цитированием
Старый 21.07.2009, 00:35   #5
Роман Радер
Форумчанин
 
Аватар для Роман Радер
 
Регистрация: 16.12.2006
Сообщений: 859
По умолчанию

Цитата:
ибо они компилятору "автоматом"
ну вот компилирую я main.cpp откуда оно знает что нужно еще f2.cpp компилить? все равно нужно проинклюдить...
а даже если и не нужно, то нафиг тогда несвязаные cpp файлы? есть один класс в f1.cpp, второй класс в f2.cpp. как создать их объекты в main.cpp если они не проинклюдены? будет ошибка про необъявленный идентификатор..
вывод - в main.cpp обязательно придется проинклюдить все остальные cppшки... или я не так понял
Роман Радер вне форума Ответить с цитированием
Старый 21.07.2009, 05:52   #6
Blade
Software Engineer
Участник клуба
 
Аватар для Blade
 
Регистрация: 07.04.2007
Сообщений: 1,618
По умолчанию

Цитата:
Сообщение от Роман Радер Посмотреть сообщение
есть один класс в f1.cpp, второй класс в f2.cpp. как создать их объекты в main.cpp если они не проинклюдены? будет ошибка про необъявленный идентификатор..
Как уже говорилось выше - создать файл f.h в котором будут объявлены соответствующие классы или прототипы нужных функций, а реализация этих функций может быть в файле *.cpp или *.c
Но вообще, нужно заметить, что все, что качается модульного программирование - условно. Никто не мешает вам писать все, например, в одном файле, или наоборот - каждую функцию в отдельном. Все это делается для удобства программиста. Вот и делайте как вам удобно
Мужество есть лишь у тех, кто ощутил сердцем страх, кто смотрит в пропасть, но смотрит с гордостью в глазах. (с) Ария
Blade вне форума Ответить с цитированием
Старый 21.07.2009, 08:49   #7
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,065
По умолчанию

Цитата:
Сообщение от Роман Радер Посмотреть сообщение
ну вот компилирую я main.cpp откуда оно знает что нужно еще f2.cpp компилить?
Не знаю как это происходит в командной строке и как это делают другие среды, но Visual C++ "отправляет" компилятору все *.cpp файлы из проекта.
Там уже видит препроцессор #include "xxx.h" и, грубо говоря, вставляет на это место содержимое соответствующего файла. Именно поэтому *.срр файлы не надо защищать от повторного включения, в отличии от хедеров.
С защитой, при попытке повторного включения файла:
Код:
#ifndef XXX_H
#define XXX_H
...
#endif
после работы препроцессора, будет "пустота". Если же убрать защиту, то один и тот же код добавится вторично и компилятор будет в недоумении: "какой из этих одинаковых классов использовать?"
Цитата:
Сообщение от Роман Радер Посмотреть сообщение
а даже если и не нужно, то нафиг тогда несвязаные cpp файлы?
А зачем вам связанные срр файлы? Как же повторное использование кода? Скопировал из другого проекта нужный модуль и компилишь себе на здоровье, а если его завязать на main.cpp, то корректировать придется каждый раз.
Цитата:
Сообщение от Роман Радер Посмотреть сообщение
есть один класс в f1.cpp, второй класс в f2.cpp. как создать их объекты в main.cpp если они не проинклюдены?
Описываем классы хоть в общем f.h или для каждого свой хедер создаем, а в срр пишем только реализацию методов. В main.cpp соответственно инклюдим этот хедер, а не f1.cpp и f2.cpp. Нам же тут главное, чтобы в main.cpp было известно о существовании класса, а его реализация безразлична.
pu4koff вне форума Ответить с цитированием
Старый 21.07.2009, 17:11   #8
pavelstraut
Пользователь
 
Регистрация: 17.07.2009
Сообщений: 91
По умолчанию

Цитата:
Не знаю как это происходит в командной строке и как это делают другие среды, но Visual C++ "отправляет" компилятору все *.cpp файлы из проекта.
Там уже видит препроцессор #include "xxx.h" и, грубо говоря, вставляет на это место содержимое соответствующего файла. Именно поэтому *.срр файлы не надо защищать от повторного включения, в отличии от хедеров.
С защитой, при попытке повторного включения файла:
Код:


#ifndef XXX_H
#define XXX_H
...
#endif

после работы препроцессора, будет "пустота". Если же убрать защиту, то один и тот же код добавится вторично и компилятор будет в недоумении: "какой из этих одинаковых классов использовать?"
Цитата:
МОжно об этом поподробнее,особенно о защите от многократного использования
почему ее не нужно ставить,ведб тогда будет сгенерирована ошибка
так же интересует как файлы в одном проекте инклудятся друг в друга
компилятор видит #include <.....h> и вставляет хедер а сипипишки как?
pavelstraut вне форума Ответить с цитированием
Старый 21.07.2009, 18:56   #9
pu4koff
Старожил
 
Аватар для pu4koff
 
Регистрация: 22.05.2007
Сообщений: 9,065
По умолчанию

Цитата:
Сообщение от pavelstraut Посмотреть сообщение
МОжно об этом поподробнее,особенно о защите от многократного использования
почему ее не нужно ставить,ведб тогда будет сгенерирована ошибка
Ну её не нужно ставить только у *.срр. Хедеры надо защищать всегда, ну за исключением хитрого какого-то использования, которое будет работать при повторном включении файла.
Цитата:
Сообщение от pavelstraut Посмотреть сообщение
так же интересует как файлы в одном проекте инклудятся друг в друга
компилятор видит #include <.....h> и вставляет хедер а сипипишки как?
сипипишки инклюдить и не стоит. Если написать: #include "Source.cpp", то этот файл подключится ровно так, как и хедер, т.е. защищать тоже придется. Только вот никогда так не делают и потому никогда не защищают их от повторного включения. Компилятору на расширения в принципе по барабану. То, что дали ему для компиляции в качестве параметра командной строки - срр, то, что в инклюдах написано - хедер.
Компилятор на входе получает кучу сипипишек, берет первую, ищет все нужные хедеры, прописанные в инклюдах, собирает из всего этого некий объектный файл для внутреннего использования и так все сипипишки перебирает. Потом все эти объектные файлы компилятся уже в exe-шник.
Отдельно обращаем внимание, что объектные файлы создаются на каждый сипипишник, а не хедер (для хедеров вообще никаких временных файлов не создается и для каждой сипипишки он подключается и обрабатывается заново). т.е. к каждой сипипишке приписывается один и тот же код хедера. Защита от повторного включения защищает только от включения одного и того же кода в объектный файл, т.е. от ситуации:
Код:
// а.h
class A
{
...
};
// b.h
#include "a.h"
class B: public A
{
...
};
// main.cpp
#include "a.h"
#include "b.h"
...
Компилим main.cpp и получается в итоге вот такое:
Код:
// Вместо #include "a.h"
class A
{
...
};
//

// Вместо #include "b.h"
// Вместо #include "a.h"
class A
{
...
};
//
class B: public A
{
...
};
//
т.е. один и тот же класс присутствует в двух экземплярах, на что линкер будет ругаться.
Если добавить защиту от копирования, то второй инклюд просто удалится и вместо него никакой код не добавится.
Если же в проект добавить еще некий Source.cpp с кодом:
Код:
#include "a.h"
#include "b.h"
...
это уже будет другая единица компиляции и защита от повторного включения тут не спасёт. У объектного файла Source.cpp будут свои экземпляры a.h и b.h, а у main.cpp - свои.
Если мы в a.h добавим строку: "int a;", то прога не скомпилится, потому что в main'е будет создана эта переменная и в Source будет она создана и линкер не поймет какой именно экземпляр и где использовать. Если же этот код и скомпилится, то будет несколько экземпляров одной и той же переменной со всеми вытекающими непонятностями во время работы программы. Потому для глобальных переменных пишем в хедерах "extern int a;", а в сипипишках уже "int a;".
Смотрим на этот код:
Код:
// test.h
#ifndef INCLUDE_COUNT
#define INCLUDE_COUNT 1
#elif (INCLUDE_COUNT == 1)
#undef INCLUDE_COUNT
#define INCLUDE_COUNT 2
#elif (INCLUDE_COUNT == 2)
#undef INCLUDE_COUNT
#define INCLUDE_COUNT 3
#endif

// a.h
#include "test.h"
int getCount();

// a.cpp
#include "a.h"
int getCount()
{
  return INCLUDE_COUNT;
}

// main.cpp
#include <iostream>
#include "test.h"
#include "test.h"
#include "a.h"

using namespace std;

int main()
{
	cout << INCLUDE_COUNT << endl; // Выведет 3, т.к. 3 инклюда test.h (еще один из a.h Тянется)
	cout << getCount() << endl; // Выведет 1, т.к. из "a.cpp" выходит только 1 инклюд test.h

	getchar();
	return 0;
}
В общем хедер для каждого сипипишника обрабатывается заново и один и тот же макрос имеет разное значение в разных срр файлах

Последний раз редактировалось pu4koff; 21.07.2009 в 19:31.
pu4koff вне форума Ответить с цитированием
Старый 21.07.2009, 21:30   #10
Роман Радер
Форумчанин
 
Аватар для Роман Радер
 
Регистрация: 16.12.2006
Сообщений: 859
По умолчанию

эксперементальным путем понял что если в хедере
a.h
Код:
int func1(int k);
int func2(float f);
и в файле с таким же именем но расширением cpp - реализация
a.cpp
Код:
int func1(int k)
{
  return k*2;
}
int func2(int f)
{
  return f+2;
}
а в main.cpp
Код:
#include "a.h"
void main()
{
  func1();
}
то будет работать. значит достаточно подключить хедер а реализацию компилятор будет искать в cpp файле такого-же имени

верно??
Роман Радер вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Ссылка на файл из текущей папки! Сбор инфы в один файл! mephist Microsoft Office Excel 11 10.07.2009 13:51
Копирование текста в файл bookkc Общие вопросы Delphi 2 18.06.2009 23:57
Чтение и Запись текста из\в файл(а), C++ FastDead2 Помощь студентам 20 14.05.2009 00:01
Дан файл, содержащий текст на русском языке.Составить в алфавитном порядке список слов в файл. JiLiYa Паскаль, Turbo Pascal, PascalABC.NET 3 26.12.2008 12:05
вывод текста в файл Индийское диско Общие вопросы Delphi 6 09.10.2007 12:43