| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Для новичков > стражи хидера не охраняют при инклуде!( |
| Автор: WiND 11.2.2010, 11:45 | ||||||||||
| Сорри, заезжанная тема, но несмотря на то, что я прочитал много и все делаю по правилам,у меня не выходит) к делу: Файлы: Client.h/Client.cpp, MyFuncs.h, main.cpp содержание: Client.h:
Client.cpp:
MyFuncs.h:
main.cpp:
даже в main.cpp добавил #pragma once ) пробовал и другой способ :#ifndef xxx #define xxx #endif Ошибки:
даже в main.cpp добавил #pragma once ) пробовал и другой способ :#ifndef xxx #define xxx #endif Вот что не так?! Мне файл MyFuncs.h в дальнейшем почти везде понадобится, а подключить получается тольк однажды. будто не работает #ifndef и #pragma once |
| Автор: xvr 11.2.2010, 12:07 | ||
| Это не стражи виноваты - они работают, иначе все развалилось бы еще на этапе компиляции, а не линковки. Это повторное определение функций (из .h) файла в нескольких единицах трансляции. Добавь inline в их определение
|
| Автор: Alca 11.2.2010, 12:45 |
| Глянь |
| Автор: Alca 11.2.2010, 12:46 |
| Разбей свой MyFuncs.h на h-ник и cpp-шник |
| Автор: bilbobagginz 12.2.2010, 15:36 | ||||
WiND терминология: файл .h - хедер (заголовок) - это место, где ты объявляешь классы, методы, и функции. файл .cpp - исходник, это место, где ты реализуешь объявленное, определяешь. единственное исключение - это inline функции/методы - когда ты их определяешь в заголовке. напр. твои функции лучше всего объявить так:
а определить так:
Использовать же функции и методы inline имеет смысл лишь в редких случаях, когда это улучшает скорость выполнения программы. т.е. когда выполнение функции значительно короче, чем прыжок в обычную функцию (т.е. сохраниение регистров процессора, стека и т.д.). Когда ты указываешь, что функция - inline, каждый ее вызов при компиляции заменяется ее кодом (похоже на макро), в отличие от обычной функции, когда каждый ее вызов переносит контроль кода в другое место, где код функции находится. Думаю правило "буравчика" в решении использовать или нет inline можно так: для сохранения регистров и др. нужной информации при вызове функции нужно несколько машинных комманд, и это ессно занимает некоторое время. Если функция-кандидат - не имеет циклов, и делает какие-то очень быстрые действия, то имеет смысл ее сделать inline, т.к. сохранение данных, стека и т.д. 2 раза займет дольше времени, чем выполнить код здесь и сейчас. А если функция - цикл (напр. strstr - обязательно цикл, и for(){} - тоже), то использовать inline - не стоит с т.з. скорости и величины программы. но я - не гуру по C++, просьба гуру C++: если я не прав прошу меня ... поправить! |
| Автор: bsa 12.2.2010, 16:18 |
| inline это рекомендация компилятору. Он может ее молча игнорировать. Что собственно и делает при отключенной оптимизации (а то невозможно отлаживать программу). Нет ничего плохого в использовании циклов внутри inline-функций. Почти вся STL состоит из inline- функций/методов. При вызове функций регистры не сохраняются. Просто эта операция не очень быстрая. По умолчанию inline лучше использовать для функций типа геттеров и сеттеров, логика которых не предполагает сложных вычислений. Обычно, они возвращают/устанавливают значение переменной класса. Так же без inline невозможно пока что делать шаблонные методы и функции. Так как далеко не все компиляторы поддерживают extern template - нельзя использовать шаблоны там, где не доступно их определение (реализация). С другой стороны, как я уже написал выше, iniline - это только рекомендация. Компилятор, если сочтет нужным, сделает ее обычной функцией, которую будет вызывать при необходимости стандартным образом. Причем, эта функция будет единой для всех единиц трансляции (т.е. дублирования кода не будет). |
| Автор: bilbobagginz 12.2.2010, 16:59 |
| |
| Автор: WiND 12.2.2010, 17:22 | ||||||
| Спасибо за ответы) Т.е без разницы, использую я inline или нет? Как лучше поступить? Так MyFuncs.h
Или так MyFuncs.h
MyFuncs.cpp
ЗЫ: Еще вопрос всплыл. Определяю макросы, где обычная конкатенация строковых литералов. с переменным числом параметров #define MSG_1(param1, param2) "MSG1 " ## param1 ## " " ## param2 #define MSG_1(param1, param2б param3) "MSG2 " ## param1 ## " " ## param2 ## " " ## param3 ... Эти макросы будут часто использоваться, соответственно будет много констант с одним и тем же текстом. Думал заменить текст в макросах на константы, но это непозволительно. Как лучше поступить? создать отдельную функцию? или создать функцию, вызывающую эти макросы, тогда кол-во их будет одинарным? Отказаться вообще от макросов? (Понимаю, дрянь эти макросы(дефайн и т.п) но почему-то меня к ним патологически тянет) |
| Автор: Alca 12.2.2010, 17:24 |
| То что я предложил Добавлено через 11 секунд |
| Автор: WiND 12.2.2010, 17:35 |
| 2Alca, А чем будет лучше тогда? лично я не хочу из-зв двух(мб 3х) мизерный функций создавать еще срр файл. просто когда много файлов - путает сознание) Но вместе с этим, хочется делать правильно) Несмотря на подробные ответы, они противоричивы и слегка сбили меня с толку) И так сходу я не понял разницы) вот и спрос )) |
| Автор: unicuum 12.2.2010, 17:46 |
Да, вот так. |
| Автор: Alca 12.2.2010, 17:54 | ||
раздутие кода 100%-во не будет |
| Автор: bilbobagginz 12.2.2010, 17:57 |
раздутие какого кода? |
| Автор: Alca 12.2.2010, 17:58 | ||||||||
а чем тебя функции не устроили? Добавлено @ 17:59
инлайного Добавлено @ 18:00
Если у него проект маленький, то пофиг что юзать. Добавлено @ 18:03
два вместо одного Добавлено @ 18:04 это у тебя тут 2-3 функции, а если 20-30? И всех их заинлайнить? Тогда возможно раздутие кода. Добавлено @ 18:13 Если на то пошло, тогда пихай классы в один файл. Меньше файлов - меньше путаниц. |
| Автор: bsa 12.2.2010, 18:51 | ||
WiND, inline нужно использовать тогда, когда без него нельзя или явно видно, что функцию надо встраивать в код (геттеры/сеттеры). В остальных случаях - используй второй вариант. |
| Автор: WiND 12.2.2010, 18:51 | ||||||
Вот это уже не так. Классы пихать в один файл, практически всегда приносит больше путаницы.
Если скажем 4 маленьких модуля по несколько функций, модули тематически разные, то получается уже не 2 вместо одного, а 8, вместо 4=) Вот выдержка из какой-то учебной книжки:
Возможно, я опять недопонял ) но если верить этому тексту, то bilbobagginz был прав в отношении подстановки. и раздутие кода походу тоже получается. Но опять же, почти все стандартные хидеры что я видел, все из inline-ов. Не может же быть так, что по сути это макросы=) Тогда получается, что, как сказал bsa, компилятор сам решает когда ему использовать фун-ю как макрос, а когда, как функцию. Стало быть, как определить, когда он что делает, только дизасмить? 2mes, спасибо за ответ ) |
| Автор: bsa 12.2.2010, 18:57 | ||
Оба утверждения верные. Когда происходит встраивание, код обычно увеличивается. |
| Автор: WiND 12.2.2010, 19:03 |
| 2mes, проверил в дизасме, оказывается он подставляет только полностью идентичные. А в случаи, если параметры макроса отличаются, адреса тоже отличаются. Логично конечно почему так получается)) А сделать так, чтобы на название команды он ссылался на один адрес, а на параметры - другой адрес. Хотя, я уже неуверен, что мне это нужно. Возможно проще ввести одну функцию, принимающую сколь угодно параметров, а в качестве первого - название команды. и через свитч подставлять макросы) Но в таком случаи, я не уверен, что цель оправдает средства) |
| Автор: mes 12.2.2010, 19:04 | ||
inline-функция и функция_помеченная_как_inline - разные вещи. 1. функция не обязательно должна быть помечена как inline чтоб стать inline-функцией 2. функция помеченная как inline не обязательно станет inline-функцией.
Это не нужно для преобладающего большинства задач. вообще то не стоит сравнивать инлайн-функцию и макрос - общего в них мало. |
| Автор: bilbobagginz 12.2.2010, 19:07 | ||
надо просто познакомиться с компилятором поближе. в общем как и указал bsa, inline - это "предложение" компайлеру. поэтому, все будет как я указал только если компайлер "решится, и пойдет на это". есть компайлеры, которых можно попросить "настоятельно", но вообще лучше не вмешиваться в этот механизм, а дать компайлеру "делать свою работу". я думаю, когда есть указание компайлеру оптимизировать на скорость, то он старается использовать инлайн почаще. но в общем это надо почитать мануальчик какого-то конкретного компайлера. |
| Автор: mes 12.2.2010, 19:09 | ||||
Ну так о том и говорилось
Ну тогда сделайте, чтоб было отдельно название, отдельно параметры у Вас же после препроцессора получается из параметров одна строка, которая и поступает компилятору. |
| Автор: WiND 12.2.2010, 19:10 | ||||
Т.е может получиться так, что какая-то гигантская функция, стала инлайн. Компилятор просто так захотел, а я ее определил в классе и не указывал inline?) Добавлено через 5 минут и 49 секунд
Тогда получится CONSTA+MACRO_COMMAND это не совсем красиво=)) Но в этом случаи придется уже использовать strcpy, а это еще лишний код) Если конечно я чего-то не знаю )) |
| Автор: mes 12.2.2010, 19:16 | ||
Теоретически - условно может.. если компилятор решит, что будет значительный выйгрыш скорости от этого на фоне скорости выполнения функции. Практически - не может, так как большая функция состоит из множества команд, на фоне общего времени выполнения которых, время лишнего вызова незначительно. |
| Автор: bsa 12.2.2010, 20:58 | ||||
Хотя, в любом случае все зависит от конкретного компилятора. Добавлено через 1 минуту и 20 секунд
|
| Автор: xvr 12.2.2010, 21:14 | ||
| Пример (очень синтетический, но все же)
Если компилятор заинлайнит func2 в func, то после этого он может поменять 2 for'а местами и сделать заполнение массива по строкам, что может быть на несколько порядков эффективнее |
| Автор: mes 12.2.2010, 21:26 |
никто, кроме разумного взгляда на необходимость такого решения. плюс говоря о большой функции я полагал, опираясь на предыдущие высказывания автора, что речь идет о функции, представляемой большим результативным(асм) кодом. Так вот например очень большой шаблон в исходных кодах часто бывает представлен малым кол-во машинных команд результативного кода и соответсвенно вполне inlineable. |
| Автор: unicuum 12.2.2010, 21:38 | ||
А ещё написано, что полагаться на поведение компилятора нельзя, лучше следовать стандарту. На вопрос автора: макросы не рекомендуют использовать, если можно обойтись без них. В страже включения они оправданы вместе с директивой #pragma once. Для записи строковых литералов однозначно нет. |
| Автор: mes 12.2.2010, 22:25 | ||||||
Да лучше, но стандарт в данном вопросе отмалчивается, оставляя принятие решения о способе хранения строковых литералов на совести разработчиков компилятора.
Не совсем так. Не рекомендуется использовать в качестве функций.
стражи включения - это один из правильных способ использования макросов. при чем тут "pragma once" и что значит "вместе" в данном контексте не понял.. какие Вы однoзначные.. a я бы с Вами не согласился Добавлено через 54 секунды насчет однозначности |
| Автор: WiND 13.2.2010, 23:29 |
| Всем спасибо=) выполняю приказ bsa)) |