Форум программистов, компьютерный форум CyberForum.ru

Раздельная компиляция (нюансы использования заголовочных файлов и файлов реализации) - C++

Восстановить пароль Регистрация
 
 
SergioO
 Аватар для SergioO
90 / 179 / 61
Регистрация: 13.12.2015
Сообщений: 981
07.01.2016, 14:01     Раздельная компиляция (нюансы использования заголовочных файлов и файлов реализации) #1
Почему во многих учебниках функции-члены класса внутри класса только объявляют, но определяют вне самого класса (не, ну как бы в классе, но вне) пример ниже

C++
1
2
3
4
5
class C {
int func(int n);// о,]объявляем
}
// дальше "выходим" из класса и определяем
int C::func(int n){return n+1;}
почему не определить сразу в классе?

C++
1
2
3
class C {
int func(int n){return n+1;};
}
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.01.2016, 14:01     Раздельная компиляция (нюансы использования заголовочных файлов и файлов реализации)
Посмотрите здесь:

C++ Подключение заголовочных файлов
Отличие заголовочных файлов C++
C++ Раздельная компиляция файлов в проекте. Межмодульное взаимодействие
C++ Объявление заголовочных файлов
Раздельная компиляция файлов C++
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
hoggy
5230 / 2121 / 404
Регистрация: 15.11.2014
Сообщений: 4,812
Завершенные тесты: 1
07.01.2016, 14:17     Раздельная компиляция (нюансы использования заголовочных файлов и файлов реализации) #2
Цитата Сообщение от SergioO Посмотреть сообщение
почему не определить сразу в классе?
1.
что бы не загромождать декларацию.

хэдер - "заголовок" по другому.
как оглавление в книге.
смотришь на прототипы, и сразу понятно,
что есть в классе, а чего нет.
это - удобно.

2.
код, похороненный в спп файле скомпиляется один раз.
а использоваться будет множеством ед. трансляций.

код, определенный в хэдере будет перекомпиляццо каждый раз заново,
для каждой очередной ед. трансляции.
каждый раз при изменении реализации,
все зависимые ед. трансляции будут заново перекомпилироваться.

это плохо для времени компиляции.


3.
сокрытие кода.

можно собрать библиотеку, и распространять её,
например, в виде product.h и product.lib
хэдер по прежнему будет содержать исходный код в виде текста,
в то время, как product.lib - там уже бинарные данные.
без специальных приседаний будет не понятно,
что там внутри.


в общем, если вкратце:
стремятся по максимуму вынести с хэдеров в cpp файл.
Kirik516
6 / 6 / 0
Регистрация: 27.12.2014
Сообщений: 66
07.01.2016, 14:20     Раздельная компиляция (нюансы использования заголовочных файлов и файлов реализации) #3
Цитата Сообщение от SergioO Посмотреть сообщение
почему во многих учебниках функции-члены класса внутри класса только объявляют, но определяют вне самого класса (не, ну как бы в классе, но вне) пример ниже
Для понимая можно посмотреть на функции в С++. Есть реализация функции, есть ее прототип. Вот объявление класса это прототип.
Цитата Сообщение от SergioO Посмотреть сообщение
// дальше "выходим" из класса и определяем
А здесь мы не выходим из него, а реализуем его метод. Так принято писать в С++.
К тому же, если реализовывать метод в объявлении класса, то программист неявно просит компилятор сделать этот метод inline.

И обратите внимание, что объявление класса принято писать в .h файлах, от слова header, т.е. в заголовочных
файлах. Грубо говоря в оглавлении, чтобы рассказать компилятору: "Смотри что у меня есть!".
Nosey
 Аватар для Nosey
1185 / 352 / 102
Регистрация: 22.10.2014
Сообщений: 791
Завершенные тесты: 2
07.01.2016, 14:20     Раздельная компиляция (нюансы использования заголовочных файлов и файлов реализации) #4
Цитата Сообщение от SergioO Посмотреть сообщение
почему во многих учебниках функции-члены класса внутри класса только объявляют, но определяют вне самого класса (не, ну как бы в классе, но вне) пример ниже
Конкретно в данном случае - если
Цитата Сообщение от SergioO Посмотреть сообщение
// дальше "выходим" из класса и определяем
Это в том же самом заголовочном файле - то делают так "потому что могут".
В случаях посложнее всё растёт из Правило одного определения (One Definition Rule, ODR)
SergioO
 Аватар для SergioO
90 / 179 / 61
Регистрация: 13.12.2015
Сообщений: 981
07.01.2016, 14:42  [ТС]     Раздельная компиляция (нюансы использования заголовочных файлов и файлов реализации) #5
Цитата Сообщение от Kirik516 Посмотреть сообщение
И обратите внимание, что объявление класса принято писать в .h файлах, от слова header, т.е. в заголовочных
файлах. Грубо говоря в оглавлении, чтобы рассказать компилятору: "Смотри что у меня есть!".
я не волшебник, я только учусь )
я делаю просто файл с классом, кладу рядом в папку и потом инструкцией
#include <class>
подключаю его без всяких .h
неправильно так?
Kirik516
6 / 6 / 0
Регистрация: 27.12.2014
Сообщений: 66
07.01.2016, 15:05     Раздельная компиляция (нюансы использования заголовочных файлов и файлов реализации) #6
Цитата Сообщение от SergioO Посмотреть сообщение
я делаю просто файл с классом, кладу рядом в папку и потом инструкцией
#include <class>
подключаю его без всяких .h
неправильно так?
Без расширений? Как стринги и все остальное из std?

Ну скорее всего тут нет четкого деления на правильно или неправильно. Поправьте, если не так.
Все зависит от того, как договорится между собой команда разработчиков.
Я предпочитаю делать два файла classname.h и classname.cpp, и писать в них заголовки и реализацию соответственно.
К тому же изначально везде учат делать именно так, как я описал.

Добавлено через 6 минут
Да, и конечно, надо учитывать те особенности, о которых писал hoggy, и особенность связанную с inline.
Nosey
 Аватар для Nosey
1185 / 352 / 102
Регистрация: 22.10.2014
Сообщений: 791
Завершенные тесты: 2
07.01.2016, 15:11     Раздельная компиляция (нюансы использования заголовочных файлов и файлов реализации) #7
Лучше называть .cpp и .h соответственно исходники и заголовочные файлы.
Цитата Сообщение от SergioO Посмотреть сообщение
#include <class>
#include <class> - поиск файла происходит сначала в системных путях.
#include "class" - сначала в пользовательских.
И использование по верхнему правилу <> "" - это используемая best practice.
SergioO
 Аватар для SergioO
90 / 179 / 61
Регистрация: 13.12.2015
Сообщений: 981
07.01.2016, 17:02  [ТС]     Раздельная компиляция (нюансы использования заголовочных файлов и файлов реализации) #8
Ну скорее всего тут нет четкого деления на правильно или неправильно. Поправьте, если не так.
Все зависит от того, как договорится между собой команда разработчиков.
Я предпочитаю делать два файла classname.h и classname.cpp, и писать в них заголовки и реализацию соответственно.
и потом подключать как
C++
1
2
#include "classname.h"
#include "classname.cpp"
?
Цитата Сообщение от Kirik516 Посмотреть сообщение
К тому же изначально везде учат делать именно так, как я описал.
вас учат, а мы сами с усами ) поэтому будем перенимать ваш опыт )

в чем преимущество поступать именно так, а не как я? ну, функции ниже класса записать как class::func(){}думаю не трудно, но принципиально то потом все закомпилится ведь...
Nosey
 Аватар для Nosey
1185 / 352 / 102
Регистрация: 22.10.2014
Сообщений: 791
Завершенные тесты: 2
07.01.2016, 17:14     Раздельная компиляция (нюансы использования заголовочных файлов и файлов реализации) #9
Цитата Сообщение от SergioO Посмотреть сообщение
вас учат, а мы сами с усами ) поэтому будем перенимать ваш опыт )
в чем преимущество поступать именно так, а не как я? ну, функции ниже класса записать как class::func(){}думаю не трудно, но принципиально то потом все закомпилится ведь...
Обязательно прочитайте пару книг из "списка литературы" в закреплённых темах.

Цитата Сообщение от SergioO Посмотреть сообщение
и потом подключать как
#include "classname.h"
#include "classname.cpp"
И если вопрос этот останется - приходите
SergioO
 Аватар для SergioO
90 / 179 / 61
Регистрация: 13.12.2015
Сообщений: 981
07.01.2016, 17:20  [ТС]     Раздельная компиляция (нюансы использования заголовочных файлов и файлов реализации) #10
Цитата Сообщение от Nosey Посмотреть сообщение
Обязательно прочитайте пару книг из "списка литературы" в закреплённых темах.
не знаю что там в списке, но у меня литература вся есть и по Си и С++ (Ритчи, Кэрниган, Страуструп, Липман, Шилдт, Пратта и тд и тп)
вот просто когда я их читаю, то и не понимаю ряд вопросов, о которых потом спрашиваю. может неправильно сразу все читать, но: Страуструп малопонятен в илу каких-то выкрутасов без объяснений, Шилдт к Си тяготеет, как я понимаю и тд. Хороший бы задачник с решениями по С++, как в математике чтобы, но чет такого не нахожу. По Си есть, но там совсем учебные примеры, например проинтегрировать то-то, разобрать строку в щепки и потом собрать по-другому, что не интересно. может я не прав. лучше заниматься с преподом и в группе, но что есть уж - другого не намечается.
Nosey
 Аватар для Nosey
1185 / 352 / 102
Регистрация: 22.10.2014
Сообщений: 791
Завершенные тесты: 2
07.01.2016, 17:34     Раздельная компиляция (нюансы использования заголовочных файлов и файлов реализации) #11
SergioO, Хорошо. уговорили, идём на встречу
Прочитайте краткий пересказ: Единица трансляции
И ещё раз вот это : Правило одного определения (One Definition Rule, ODR)

И как следует подумайте над прочитанным.
Вы всё ещё хотите писать
Код
#include "classname.cpp"
?

Внизу темы ещё кучка подобных тем.
Kirik516
6 / 6 / 0
Регистрация: 27.12.2014
Сообщений: 66
07.01.2016, 17:39     Раздельная компиляция (нюансы использования заголовочных файлов и файлов реализации) #12
Цитата Сообщение от SergioO Посмотреть сообщение
в чем преимущество поступать именно так, а не как я? ну, функции ниже класса записать как class::func(){}думаю не трудно, но принципиально то потом все закомпилится ведь...
Подключать в этом случает надо так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// h_file.h
#include <all>
#include <used>
#include <headers>
 
class DeclareTheClass
{
// объявляем то, что нам нужно
};
 
//cpp_file.cpp
#include "h_file.h"
 
// реализуем все, что нужно
 
//main_file.cpp
#include "h_file.h"
 
// точка входа в программу
Для чего это делается?
Если реализовать класс внутри его объявление, ты вы неявно попросите компилятор сделать все методы inline.
Чтобы контролировать эти просьбы нужно разделить реализацию и объявление.
Если реализовывать методы в том же файле, что и объявление, то при каждом подключение этого файла, будет
копироваться код реализации. И скорее всего при многократном подключении этого файла, вы получите ошибку
о том, что один и тот же метод несколько раз реализован.
Так как директива #include <some_file> заставит препроцессор полностью скопировать содержание этого файла
в место вызова директивы.

Также hoggy, довольно подробно описал значимость разделения объявления и реализации.

Также не стоит забывать и о следующей конструкции в заголовочных файла, которая предотвращает бесконечное
вложение.
C++
1
2
3
4
5
//h_file.h
#ifndef H_FILE_H
#define H_FILE_H
// все что нам нужно
#endif // H_FILE_H
Добавлено через 2 минуты
Цитата Сообщение от SergioO Посмотреть сообщение
Хороший бы задачник с решениями по С++, как в математике чтобы, но чет такого не нахожу.
Есть в интернете сайты, к сожалению не помню адресов, для подготовки к олимпиадам по программированию.
В них хорошие задачи. Причем, там есть система проверки ответа. Загружаете программу на сайт и она там тестируется
автоматически.
SergioO
 Аватар для SergioO
90 / 179 / 61
Регистрация: 13.12.2015
Сообщений: 981
07.01.2016, 17:53  [ТС]     Раздельная компиляция (нюансы использования заголовочных файлов и файлов реализации) #13
Цитата Сообщение от Nosey Посмотреть сообщение
Прочитайте краткий пересказ: Единица трансляции
вот который раз убеждаюсь что наглядно должны такие вопросы разбираться - как говорил Пуанкаре:"чтобы объяснить обыкновенные дроби нужен нож и торт". на словах все это, особенно новичку мало понятно. вот бы схемкой как типа "мультик" )) "лежит" файлик и тут компилятор его берет и что дальше происходит, что куда включается и не включается... сам бы уже такую фигню сделал, но я подобными пакетами не владею. не хотите заняться? ))

Добавлено через 3 минуты
Цитата Сообщение от Kirik516 Посмотреть сообщение
Так же не стоит забывать и о следующей конструкции в заголовочных файла, которая предотвращает бесконечное
вложение.
а
C++
1
#pragma once
разве не с этой целью или я чего-то путаю?

C++
1
#ifndef
вроде для макросов используется
Nosey
 Аватар для Nosey
1185 / 352 / 102
Регистрация: 22.10.2014
Сообщений: 791
Завершенные тесты: 2
07.01.2016, 17:54     Раздельная компиляция (нюансы использования заголовочных файлов и файлов реализации) #14
Цитата Сообщение от Kirik516 Посмотреть сообщение
Если реализовать класс внутри его объявление, ты вы неявно попросите компилятор сделать все методы inline.
Мы не просим компилятор, мы лишь даём ему такую возможность, предоставляя код в данной единице трансляции(в cpp файле).
А если он не будет видеть реализацию, а только определение - то оставит это на откуп линковщику -> в общем случае инлайнинга не произойдёт.

Цитата Сообщение от Kirik516 Посмотреть сообщение
Так же не стоит забывать и о следующей конструкции в заголовочных файла, которая предотвращает бесконечное
вложение.
Это называется header guards.

Вот это ещё можно добавить к верхнему списку ссылок:
Компилятор - С++ использует раздельную компиляцию.
hoggy
5230 / 2121 / 404
Регистрация: 15.11.2014
Сообщений: 4,812
Завершенные тесты: 1
07.01.2016, 18:03     Раздельная компиляция (нюансы использования заголовочных файлов и файлов реализации) #15
Цитата Сообщение от Nosey Посмотреть сообщение
Мы не просим компилятор, мы лишь даём ему такую возможность,
нет, мы именно что просим.
все методы определённые в декларации класса неявно помечаются inline
0x10
2426 / 1598 / 232
Регистрация: 24.11.2012
Сообщений: 3,919
07.01.2016, 18:06     Раздельная компиляция (нюансы использования заголовочных файлов и файлов реализации) #16
Цитата Сообщение от SergioO Посмотреть сообщение
вот который раз убеждаюсь что наглядно должны такие вопросы разбираться
Цитата Сообщение от SergioO Посмотреть сообщение
сам бы уже такую фигню сделал, но я подобными пакетами не владею. не хотите заняться?
Задумайтесь на минуту: может ли быть такое, что Вы — единственный в мире, кто задается этими вопросами? Скорее всего, нет. Кажется ли этот материал достаточно общим и базовым, чтобы его основы нужно было объяснять людям? Скорее всего, да. Следовательно, материалы должны быть. Вы их искали? Книги, статьи в гугле, видео на ютубе? Один запрос «Compilation process» выдает кучу результатов, на любой вкус. Понятно, что отвечать за качество подачи материала каждого никто не станет, тем не менее источников информации предостаточно.

Одна из первых попавшихся статей с диаграммами и листингами: link.
Nosey
 Аватар для Nosey
1185 / 352 / 102
Регистрация: 22.10.2014
Сообщений: 791
Завершенные тесты: 2
07.01.2016, 18:09     Раздельная компиляция (нюансы использования заголовочных файлов и файлов реализации) #17
Цитата Сообщение от hoggy Посмотреть сообщение
все методы определённые в декларации класса неявно помечаются inline
На которую ему с высокой колокольни, если мы не включим оптимизацию.
А если включим оптимизацию, то он заинлайнит всё что сможет, помечена она или нет.

Если не учитывать верхнее, то потом возникнет вопрос "Что происходит при использовании ключевого слова inline?"
SergioO
 Аватар для SergioO
90 / 179 / 61
Регистрация: 13.12.2015
Сообщений: 981
07.01.2016, 18:13  [ТС]     Раздельная компиляция (нюансы использования заголовочных файлов и файлов реализации) #18
Скачал книгу А.Ахо "Компиляторы. Принципы, технологии и инструментарий". буду пробовать ))

Добавлено через 1 минуту
Цитата Сообщение от Nosey Посмотреть сообщение
Если не учитывать верхнее, то потом возникнет вопрос "Что происходит при использовании ключевого слова inline?"
вроде как и ничего даже ) а если функция коротенькая, то может и чего
hoggy
5230 / 2121 / 404
Регистрация: 15.11.2014
Сообщений: 4,812
Завершенные тесты: 1
07.01.2016, 18:27     Раздельная компиляция (нюансы использования заголовочных файлов и файлов реализации) #19
Цитата Сообщение от Nosey Посмотреть сообщение
На которую ему с высокой колокольни, если мы не включим оптимизацию.
А если включим оптимизацию, то он заинлайнит всё что сможет, помечена она или нет.
монопенисуальный фактор.

выше вы писали, что мы ни о чем не просим компилятор,
а лишь предоставляем ему какие то возможности.

ну так вот, мы именно, что просим заинлайнить.
мы сообщаем компилятору:
крутись, как хочешь, но эту функцию мы полагаем встраиваемой.

и мы имеем полное право так полагать.
стандарт нам это гарантирует.

простейший пример:
мы поклали болт на ODR, но ошибок множественного определения не происходит.
потому что стандарт гарантирует иммунитет для inline функций.

при этом нам абсолютно фиолетово,
дебаг у нас сейчас, или оптимизации.
и вообще, сможет ли компилятор реально оптимизировать,
или нет.

inline - ключевое слово языка.
синтаксис - первичен.
любые оптимизации - вторичны.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.01.2016, 18:40     Раздельная компиляция (нюансы использования заголовочных файлов и файлов реализации)
Еще ссылки по теме:

не разберусь как переработать программу с учетом использования заголовочных файлов, модулей и пользовательских функций C++
Подключение заголовочных файлов C++
Подключение заголовочных файлов и файлов реализации C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
Kirik516
07.01.2016, 18:40     Раздельная компиляция (нюансы использования заголовочных файлов и файлов реализации)
  #20

Не по теме:

Цитата Сообщение от SergioO Посмотреть сообщение
C++
1
#pragma once
разве не с этой целью или я чего-то путаю?
Это все ваши MSVS упоротости. А я под MinGW сижу.

Цитата Сообщение от Nosey Посмотреть сообщение
Это называется header guards.
Название то красивое. Но его могли не понять.

Yandex
Объявления
07.01.2016, 18:40     Раздельная компиляция (нюансы использования заголовочных файлов и файлов реализации)
Ответ Создать тему
Опции темы

Текущее время: 11:02. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru