Здравствуйте, e-buch, Вы писали:
EB>Ворос по теме — как лучше организовать проект ? EB>1. определение и реализация класса в одном файле *.h EB>2. определение и реализация класса в двух файлах *.h & *.cpp
Если класс шаблонный — то его объявление и определение должны быть в заголовочном файле. Иногда, для красоты, делают так:
// class.h#ifndef __class_h__
#define __class_h__
template <.....> class XXX
{
.......
};
...
#include"class_impl.h"#endif/////////////////////////////////////
// class_impl.h#ifndef __class_impl_h__
#define __class_impl_h__
#include"class.h"// на тот случай, если кто-то захочет включить
// class_impl.h без class.htemplate <.....> XXX::XXX() {...}
template <.....> void XXX::abcd() {...}
...
#endif
Если же класс / функция / глобальная переменная не шаблонная, то
— объявление — в заголовочном файле
— определение — в компилируемом.
Причем, хотя определение функции/переменной автоматически является объявлением,
очень рекомендуется включать "родной" заголовочник в компилируемый файл.
Это позволит ловить ошибки — расхождения между объявлением и определением.
Здравствуйте, UgN, Вы писали:
UgN>Просто, если один и тот же заголовочный файл нужен и .cpp и .h, то почему бы не оставить его только в .h? UgN>Или я чего-то не догоняю?
Можно и так, но если в включаемом фаеле есть страж, то он то все равно два раза невключится
Вопрос глупвй,но я пытаюсь с этим разобраться уже давно так что не бейте меня, а лучше поделитесь опытом...
Проблемма такая: я не могу понять как происходит компиляция когда используется много файлов cpp и h Мне приходится просто наугад вставлять #include "***.h" где попало, а потом проверять компилится или нет Вот например есть два класса в четырех файлах First.cpp First.h Second.cpp Second.h и файл Main.cpp с функцией WinMain
в обоих классах используется объекты из файла d3d8.h, вот как в них подключены заголовочные файлы:
..да в First.h используется Second.h First.cpp:
Здравствуйте, Tora-Bora, Вы писали:
TB>Вопрос глупвй,но я пытаюсь с этим разобраться уже давно так что не бейте меня, а лучше поделитесь опытом...
Если используеться клас описаный в заголовке — включаешь его.
если же только указатель, то пишешь class ...; вроде всё.
если получаеться что в одном заголовке нужно что то из первого, а первому из второго — напрягаешь извилину и правишь, что бы такого не было...
Здравствуйте, ssm, Вы писали:
ssm>Используй следующее 2 простых правила, и забудь о своих проблемах:
ssm>1. В каждый хидер вставляй страж:
ssm>
ssm>//myheader.h
ssm>#ifndef __MYHEADER_H__
ssm>#define __MYHEADER_H__
ssm>//тут твой код
ssm>#endif//__MYHEADER_H__
ssm>
ssm>2. Все хидеры должны быть самодостаточными, тоесть он должен включать все хидеры, необходимые для его компиляции
Ну я включаю эти дефайны, а насчет второго правила: я там в примере показал, они все самодостаточные, ведь в main.cpp нужен только First.h, а он не компилится без d3d8.h и second.h, хотя они нужны только в First.cpp
Re[2]: Проблемма с заголовочными файлами
От:
Аноним
Дата:
23.04.03 14:40
Оценка:
Здравствуйте, ssm, Вы писали:
ssm>Используй следующее 2 простых правила, и забудь о своих проблемах:
Здравствуйте, Tora-Bora, Вы писали:
TB>Ну я включаю эти дефайны, а насчет второго правила: я там в примере показал, они все самодостаточные, ведь в main.cpp нужен только First.h, а он не компилится без d3d8.h и second.h, хотя они нужны только в First.cpp
Тут ты немного непонял, вот в общем виде(будет работать всегда):
//first.h #ifdef __first_h__
#define __first_h__
#include <windows.h> //если для декланации класса First надо windows.h#include <D3D8.h> //если для декланации класса First надо D3D8.h#include"second.h"//если для декланации класса First надо second.h
//декланация класса First#endif//__first_h__
//second.h#ifdef __second_h__
#define __second_h__
#include <windows.h> //если для декланации класса Second надо windows.h#include <D3D8.h> //если для декланации класса Second надо D3D8.h
//декланация класса Second#endif//__second_h__
//First.cpp #include"First.h"#include <windows.h> //если для реализации класса First надо windows.h#include <D3D8.h> //если для реализации класса First надо D3D8.h#include"second.h"//если для реализации класса First надо second.h
//реализация класса First
//Second.cpp#include"Second.h"#include <windows.h> //если для реализации класса Second надо windows.h#include <D3D8.h> //если для реализации класса Second надо D3D8.h
//реализация класса Second
//Main.cpp#include <windows.h> //если для реализации main надо windows.h#include <D3D8.h> //если для реализации main надо D3D8.h#include"second.h"//если для реализации main надо декларация Second#include"first.h"//если для реализации main надо декларация Secondint main(){
//...return 0;
}
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, ssm, Вы писали:
ssm>Используй следующее 2 простых правила, и забудь о своих проблемах:
А>... до поры-до времени.
сказал А говори и B, или это ты о precompiled headers?
Re[4]: Проблемма с заголовочными файлами
От:
Аноним
Дата:
23.04.03 15:21
Оценка:
Здравствуйте, ssm, Вы писали:
ssm>Используй следующее 2 простых правила, и забудь о своих проблемах:
А>... до поры-до времени.
ssm>сказал А говори и B, или это ты о precompiled headers?
В достаточно изощренных случаях можно придти к тому, что эти правила работать перестанут. Тогда придется сесть и с карандашиком повычерчивать зависимости между именами. На БОЛЬШОМ ватмане.
Re[6]: Проблемма с заголовочными файлами
От:
Аноним
Дата:
23.04.03 15:46
Оценка:
Здравствуйте, ssm, Вы писали:
ssm>Пример!!!
Понимаешь, нередко может случиться так, что два-три класса (или шаблона) очень сильно зависят друг от друга, причем обращаясь к членам друг друга.
Когда у тебя все объявления — в .h, а определения — в .cpp, все просто. Но, во-первых, бывает так, что объекты имеют методы настолько крохотные, а требования к быстродействию настолько серьезны, что хочется применять вставку по месту (inlining). А во-вторых, шаблоны — они еще могут добавить путаницы в такой ситуации.
Впрочем, я написал, что это довольно изощренная ситуация. Разрешается она легко, но от заповедей приходится отступать.
Здравствуйте, ssm, Вы писали:
TB>Ну я включаю эти дефайны, а насчет второго правила: я там в примере показал, они все самодостаточные, ведь в main.cpp нужен только First.h, а он не компилится без d3d8.h и second.h, хотя они нужны только в First.cpp
ssm>Тут ты немного непонял, вот в общем виде(будет работать всегда):
ssm>Давай файлы, тогда будет без "если"
А, ну так у меня работает, только мне говорили что в сами заголовочные файлы включать другие файлы нехорошо
А>Понимаешь, нередко может случиться так, что два-три класса (или шаблона) очень сильно зависят друг от друга, причем обращаясь к членам друг друга.
А>Когда у тебя все объявления — в .h, а определения — в .cpp, все просто. Но, во-первых, бывает так, что объекты имеют методы настолько крохотные, а требования к быстродействию настолько серьезны, что хочется применять вставку по месту (inlining). А во-вторых, шаблоны — они еще могут добавить путаницы в такой ситуации.
А>Впрочем, я написал, что это довольно изощренная ситуация. Разрешается она легко, но от заповедей приходится отступать.
Давай пример!, тем более если всего "два-три класса (или шаблона)"...
А то разглогольствовать мы все мастера
Re[8]: Проблемма с заголовочными файлами
От:
Аноним
Дата:
23.04.03 17:20
Оценка:
Здравствуйте, ssm, Вы писали:
ssm>Давай пример!, тем более если всего "два-три класса (или шаблона)"...
Эге, разбежался! Во-первых, я не имею права публиковать имеющийся у меня в разработке код. Во-вторых, писать пример, воспроизводящий ситуацию, мне лень , потому что, и это в-третьих, он будет довольно велик.
Что ты так волнуешься? Можно подумать, что правила декомпозиции кода (h-cpp) священны?
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, ssm, Вы писали:
ssm>Давай пример!, тем более если всего "два-три класса (или шаблона)"...
А>Эге, разбежался! Во-первых, я не имею права публиковать имеющийся у меня в разработке код. Во-вторых, писать пример, воспроизводящий ситуацию, мне лень , потому что, и это в-третьих, он будет довольно велик.
Однозначно
А>Что ты так волнуешься?
Я волнуюсь когда мне денег на пиво недостает, либо на рыбалке.
А>Можно подумать, что правила декомпозиции кода (h-cpp) священны?
Здравствуйте, Tora-Bora, Вы писали:
TB>А, ну так у меня работает, только мне говорили что в сами заголовочные файлы включать другие файлы нехорошо
Зря говорили.
Каждый файл (будь то h или cpp) должен быть самодостаточен.
Если тебе нужно воспользоваться файлом abc.h, то ты не обязан помнить, что для этого ты должен в правильном порядке (!) включить еще до дури файлов.
А если содержимое abc.h поменяется, и он станет требовать включения еще чего-нибудь... Не переписывать же все исходники, где он упомянут.
То же самое касается дефайнов. Желательно, чтобы дефайн был или глобальным (и определялся в сборщике проекта — т.е. *.dsp или makefile), или объявлялся по месту использования (например, во включаемом заголовочнике).
Местный дефайн, влияющий на заголовочник
#define XXX yyy
#include"abc.h"// в нем используется XXX
это неисчерпаемый источник ошибок, которые практически невозможно отладить.
Например, в abc.h объявляется класс, размер которого зависит от XXX. Два cpp-файла, использующие этот класс при разных XXX, будут иметь необычайный сэкс со стрельбой по памяти.
Здравствуйте
Ворос по теме — как лучше организовать проект ?
1. определение и реализация класса в одном файле *.h
2. определение и реализация класса в двух файлах *.h & *.cpp
ssm>//first.h
ssm>#ifdef __first_h__
ssm>#define __first_h__
ssm>#include <windows.h> //если для декланации класса First надо windows.h
ssm>#include <D3D8.h> //если для декланации класса First надо D3D8.h
ssm>#include"second.h"//если для декланации класса First надо second.h
ssm>//декланация класса First
ssm>#endif//__first_h__
ssm>
ssm>
ssm>//First.cpp
ssm>#include"First.h"
ssm>#include <windows.h> //если для реализации класса First надо windows.h
ssm>#include <D3D8.h> //если для реализации класса First надо D3D8.h
ssm>#include"second.h"//если для реализации класса First надо second.h
ssm>//реализация класса First
ssm>
А зачем в First.cpp еще раз прописывать second.h, windows.h, D3D8.h ???
Они ведь уже есть в First.h, а First.h всегда будет включаться в First.cpp.
И вообще, почему бы не указывать все необходимые для реализации класса ????.cpp заголовки только в ????.h файлах?
Здравствуйте, UgN, Вы писали:
UgN>А зачем в First.cpp еще раз прописывать second.h, windows.h, D3D8.h ??? UgN>Они ведь уже есть в First.h, а First.h всегда будет включаться в First.cpp.
Так дело все в том, что если second.h, windows.h, D3D8.h нужны только для реализации то мы их в First.h не прописываем, их место только в First.cpp
UgN>И вообще, почему бы не указывать все необходимые для реализации класса ????.cpp заголовки только в ????.h файлах?
Потому, что:
1. Хидер будет полностью самодостаточен и без них
2. Зачем мне каждый раз компилить файлы необходимые для реализации класса, если я клиент этого класса?
Здравствуйте, ssm, Вы писали:
UgN>А зачем в First.cpp еще раз прописывать second.h, windows.h, D3D8.h ??? UgN>Они ведь уже есть в First.h, а First.h всегда будет включаться в First.cpp.
ssm>Так дело все в том, что если second.h, windows.h, D3D8.h нужны только для реализации то мы их в First.h не прописываем, их место только в First.cpp
Ну да, каждый .cpp и .h имеет необходимый и достаточный набор подключаемых заголовочных файлов.
Просто, если один и тот же заголовочный файл нужен и .cpp и .h, то почему бы не оставить его только в .h?
Здравствуйте, Bell, Вы писали:
B>Потому что это приводит к увеличению взаимосвязей между модудями, и к увеличению времени перекомпиляции при изменении одного хедера.
Здравствуйте, ssm, Вы писали:
UgN>Просто, если один и тот же заголовочный файл нужен и .cpp и .h, то почему бы не оставить его только в .h? UgN>Или я чего-то не догоняю?
ssm>Можно и так, но если в включаемом фаеле есть страж, то он то все равно два раза невключится