![]() |
|
Модераторы: Daevaorn |
![]()
|
|
| d06osipov |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 72 Регистрация: 1.11.2006 Репутация: нет Всего: нет |
Я много раз слышал, что объявление функций и статических данных нужно размещать в .cpp файле, иначе будет multiple definition, что и происходит. Но, например, Boost целиком состоит только из hpp файлов, в которых, следовательно, содержаться и определения функций. Как так получается, что при подключении в двух файлов одной библиотеки Boost, не возникает multiple definition? И вообще, какие существуют принципы написания библиотек, если не хочется делать объектных файлов для библиотеки --- их создание усложняет использование и не позволяет делать оптимизацию.
Всякие конструкции вида
не помогают. |
|||
|
||||
| bsa |
|
||||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
d06osipov, ты просто не понимаешь, что происходит. У буста, кстати, тоже есть библиотеки, которые надо цеплять (например, program_options, thread и др.). Только некоторые вещи реализованы как встраиваемые (inline), а другие - просто шаблонные. В первом случае компилятор каждый раз вместо вызова функции подставляет ее код, во втором случае он может, как вставить код, так и сделать вызов. Но в любом случае код генерится для каждой реализации шаблона.
Так можно определить встраиваемую функцию:
|
||||
|
|||||
| Damarus |
|
|||
![]() Опытный ![]() ![]() Профиль Группа: Awaiting Authorisation Сообщений: 671 Регистрация: 6.5.2006 Репутация: 6 Всего: 29 |
||||
|
||||
| UnrealMan |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 27 Всего: 32 |
В первом случае он тоже может сделать вызов. inline-овость функции в этом плане компилятором может игнорироваться вообще. Кроме того, inline-функциями являются не только функции, объявленные с ключевым словом inline, но и все методы, определённые внутри определения класса. Главным отличием inline-функций от нешаблонной не-inline в данном случае является то, что определение inline-функции может и должно дублироваться в каждой единице трансляции, где данная функция используется. Это сообщение отредактировал(а) UnrealMan - 7.9.2007, 22:46 |
|||
|
||||
| d06osipov |
|
||||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 72 Регистрация: 1.11.2006 Репутация: нет Всего: нет |
Если бы я понимал, что происходит, я бы, наверное, не создавал эту тему. Например, я не понимаю, как компилятор допускает описание одного и того же класса в разных файлах и что происходит, если этот класс описан по-разному, и как это диагностируется, если как-то диагностируется.
Значит, inline функции всё-таки, вопреки принципу, ставить inline только там, где это действительно необходимо, рекомендуется применять при разработке библиотек. Интересный момент --- если инлайновость и игнорируется семантически, то не игнорируется синтаксически (не создаёт multiple definition). А на шаблонные, как я только что заметил, компилятор действительно не ругается. |
||||
|
|||||
| UnrealMan |
|
||||||
|
Опытный ![]() ![]() Профиль Группа: Участник Сообщений: 722 Регистрация: 30.3.2006 Репутация: 27 Всего: 32 |
Всё это описано в стандарте:
Копипаст не очень качественный получился, лучше в оригинал заглянуть. |
||||||
|
|||||||
| bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
Очень просто. Каждый *.cpp файл превращается в объектный файл. У этого объектного файла есть таблица экспортируемых символов - нестатических функции и переменных, определенных в этом *.cpp файле. Когда линковщик начинает объединять все объектные файлы он читает эти таблицы всех файлов и, в случае обнаружения двух одинаковых символов, ругается. Так что дело тут не столько в inline, сколько в static. Не забывай, компилятор совсем не обязан выполнять директиву inline |
|||
|
||||
| d06osipov |
|
||||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 72 Регистрация: 1.11.2006 Репутация: нет Всего: нет |
Здесь уже писалось, что компилятор может семантически не воспринимать inline, но дублироваться в каждом модуле такая функция обязана.
Эксперементально проверено на нескольких компиляторах: разрешаются в разных единицах трансляции классы с одинаковыми именами. Это же подтверждается Стандартом. |
||||
|
|||||
| archimed7592 |
|
||||
![]() Архимед ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2531 Регистрация: 12.6.2004 Где: Moscow Репутация: 58 Всего: 93 |
Хочешь сказать эти два модуля можно будет скомпоновать
-------------------- If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas. © George Bernard Shaw |
||||
|
|||||
| bsa |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Модератор Сообщений: 9185 Регистрация: 6.4.2006 Где: Москва, Россия Репутация: 63 Всего: 196 |
А ты возьми и попробуй собрать проект с полной оптимизацией (когда inline скорее всего встраивается) и без оптимизации вообще (когда не встраивается). И ты поймешь, зачем нужен static. |
|||
|
||||
| d06osipov |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 72 Регистрация: 1.11.2006 Репутация: нет Всего: нет |
||||
|
||||
| archimed7592 |
|
|||
![]() Архимед ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2531 Регистрация: 12.6.2004 Где: Moscow Репутация: 58 Всего: 93 |
А если не определять функциональность класса, то от него не особо много пользы получается... -------------------- If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas. © George Bernard Shaw |
|||
|
||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 53 Всего: 183 |
В том смысле, что все соберется без замечаний - да, это верно, если файлы не "пересекаются"... Но вот при работе возможны всякие чудеса... Правда, я с этим сталкивалась конкретно в Вижуал С и в ситуации, когда мелкие статические объекты регистрировались в общем контейнере... Так вот, при одинаковых именах классов компилятор их путал (один вместо другого вызывался). Так занимательно искать баг было... Так что лучше этого всячески избегать: использовать, скажем, пространства имен... -------------------- ... |
|||
|
||||
| archimed7592 |
|
|||
![]() Архимед ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2531 Регистрация: 12.6.2004 Где: Moscow Репутация: 58 Всего: 93 |
А если с одним именем класса код получается элегантнее и лаконичнее, то безымянное пространство имён - очень удобно. Кстати, я вообще не понимаю, зачем экспортировать из модуля какие-либо имена, относящиеся к деталям реализации. Я даже вспомогательные ф-ции не гнушаюсь оформлять в безымянном пространстве, даже если эти ф-ции находятся не в глобальном пространстве имён. -------------------- If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas. © George Bernard Shaw |
|||
|
||||
| Earnest |
|
|||
![]() Эксперт ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 5962 Регистрация: 17.6.2005 Где: Рязань Репутация: 53 Всего: 183 |
В принципе да. Но когда код разрастается, приходится его как-то делить - с большими файлами работать неудобно. Кстати, одинаковые имена классов приводят к проблемам, даже если они больше нигде (кроме как в родном cpp-файле) не видны. Безымянные пространства имен автоматически делают имена уникальными. Но, скажем, MFC с его как-бы-рантайм классами и макросами пространства имен до лампочки. Короче, в больших проектах нельзя имена пускать на самотек: кто как хочет. Нужно определить какую-то политику и всем ее придерживаться. Тогда дублирования имен проще избежать. И код чужой читать будет легче, кстати. -------------------- ... |
|||
|
||||
| archimed7592 |
|
|||
![]() Архимед ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2531 Регистрация: 12.6.2004 Где: Moscow Репутация: 58 Всего: 93 |
Ну есть у меня некая helper ф-ция, нужная ф-циям f1, f2 и f3. Если она нужно только этим ф-циям и эти ф-ции логически должны быть в одном модуле, то anonymous namespace. Если эта helper ф-ция нужна ф-циям из нескольких модулей, к примеру, какая-нибудь доработаная версия станадртного алгоритма или просто ф-ция "общего назначения"(хоть и использующаяся всего 3-4 ф-циями), то не грех её в своё пространство имён запихать(и в отдельный модуль). -------------------- If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas. © George Bernard Shaw |
|||
|
||||
| zkv |
|
|||
![]() ![]() ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 2133 Регистрация: 23.7.2006 Где: Санкт-Петербург Репутация: 26 Всего: 92 |
||||
|
||||
| archimed7592 |
|
|||
![]() Архимед ![]() ![]() ![]() ![]() Профиль Группа: Завсегдатай Сообщений: 2531 Регистрация: 12.6.2004 Где: Moscow Репутация: 58 Всего: 93 |
Недождёшься Я MFC не знаю(в частности не знаю о каких макросах тут идёт речь), не использую(и не собираюсь), а людей, умеющих грамотно использовать MFC считаю богами программирования и проектной мысли(это ж надо такое <censored> умудриться грамотно использовать -------------------- If you have an apple and I have an apple and we exchange apples then you and I will still each have one apple. But if you have an idea and I have an idea and we exchange these ideas, then each of us will have two ideas. © George Bernard Shaw |
|||
|
||||
| d06osipov |
|
|||
|
Шустрый ![]() Профиль Группа: Участник Сообщений: 72 Регистрация: 1.11.2006 Репутация: нет Всего: нет |
Объясняю зачем. Я пишу библиотеку. Из примера Boost я знаю, что оптимизация лучше работает, если библиотека не содержит объектных файлов, а подаётся целиком в исходниках. Вот и всё. А все имена у меня и есть в namespace, причём не безымянном.
|
|||
|
||||
![]()
|
| Правила форума "С++:Общие вопросы" | |
|
|
Добро пожаловать!
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | C/C++: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |