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

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
SergioO
95 / 184 / 63
Регистрация: 13.12.2015
Сообщений: 999
#1

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

07.01.2016, 14:01. Просмотров 602. Ответов 21
Метки нет (Все метки)

Почему во многих учебниках функции-члены класса внутри класса только объявляют, но определяют вне самого класса (не, ну как бы в классе, но вне) пример ниже

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;};
}
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
07.01.2016, 14:01
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Раздельная компиляция (нюансы использования заголовочных файлов и файлов реализации) (C++):

Подключение заголовочных файлов и файлов реализации - C++
Здравствуйте,при создании класса в visual studio руками не компилится проект,при создании через add class все работает,для примера написал...

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

Раздельная компиляция файлов в проекте. Межмодульное взаимодействие - C++
Задан проект-модель почтового сервера Созданы файлы: интерфейс сервера: server.h, интерфейс клиента-client.h, реализации...

не разберусь как переработать программу с учетом использования заголовочных файлов, модулей и пользовательских функций - C++
#include <iostream.h> #include <stdio.h> #include <conio.h> #include <stdlib.h> #include <string.h> FILE *fl; ...

Про добавление заголовочных файлов в заголовочных файлах - C++
В который раз эта вещь засовывает мозги в блендер! Я про то, что не могу однозначно запомнить (основываясь на моих знаниях о директиве...

Раздельная компиляция: что помещать в заголовочные файлы, а что в файлы реализации (исходники)? - C++
Здравствуйте, я учусь пользоваться Visual Studio.Пишу программу, в которой создаются и разрушаются объекты, определенного пользователем...

21
hoggy
6654 / 2842 / 487
Регистрация: 15.11.2014
Сообщений: 6,294
Завершенные тесты: 1
07.01.2016, 14:17 #2
Цитата Сообщение от SergioO Посмотреть сообщение
почему не определить сразу в классе?
1.
что бы не загромождать декларацию.

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

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

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

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


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

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


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

И обратите внимание, что объявление класса принято писать в .h файлах, от слова header, т.е. в заголовочных
файлах. Грубо говоря в оглавлении, чтобы рассказать компилятору: "Смотри что у меня есть!".
0
Nosey
1348 / 399 / 107
Регистрация: 22.10.2014
Сообщений: 861
Завершенные тесты: 2
07.01.2016, 14:20 #4
Цитата Сообщение от SergioO Посмотреть сообщение
почему во многих учебниках функции-члены класса внутри класса только объявляют, но определяют вне самого класса (не, ну как бы в классе, но вне) пример ниже
Конкретно в данном случае - если
Цитата Сообщение от SergioO Посмотреть сообщение
// дальше "выходим" из класса и определяем
Это в том же самом заголовочном файле - то делают так "потому что могут".
В случаях посложнее всё растёт из Правило одного определения (One Definition Rule, ODR)
1
SergioO
95 / 184 / 63
Регистрация: 13.12.2015
Сообщений: 999
07.01.2016, 14:42  [ТС] #5
Цитата Сообщение от Kirik516 Посмотреть сообщение
И обратите внимание, что объявление класса принято писать в .h файлах, от слова header, т.е. в заголовочных
файлах. Грубо говоря в оглавлении, чтобы рассказать компилятору: "Смотри что у меня есть!".
я не волшебник, я только учусь )
я делаю просто файл с классом, кладу рядом в папку и потом инструкцией
#include <class>
подключаю его без всяких .h
неправильно так?
0
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.
2
Nosey
1348 / 399 / 107
Регистрация: 22.10.2014
Сообщений: 861
Завершенные тесты: 2
07.01.2016, 15:11 #7
Лучше называть .cpp и .h соответственно исходники и заголовочные файлы.
Цитата Сообщение от SergioO Посмотреть сообщение
#include <class>
#include <class> - поиск файла происходит сначала в системных путях.
#include "class" - сначала в пользовательских.
И использование по верхнему правилу <> "" - это используемая best practice.
1
SergioO
95 / 184 / 63
Регистрация: 13.12.2015
Сообщений: 999
07.01.2016, 17:02  [ТС] #8
Ну скорее всего тут нет четкого деления на правильно или неправильно. Поправьте, если не так.
Все зависит от того, как договорится между собой команда разработчиков.
Я предпочитаю делать два файла classname.h и classname.cpp, и писать в них заголовки и реализацию соответственно.
и потом подключать как
C++
1
2
#include "classname.h"
#include "classname.cpp"
?
Цитата Сообщение от Kirik516 Посмотреть сообщение
К тому же изначально везде учат делать именно так, как я описал.
вас учат, а мы сами с усами ) поэтому будем перенимать ваш опыт )

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

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

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

Внизу темы ещё кучка подобных тем.
0
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 Посмотреть сообщение
Хороший бы задачник с решениями по С++, как в математике чтобы, но чет такого не нахожу.
Есть в интернете сайты, к сожалению не помню адресов, для подготовки к олимпиадам по программированию.
В них хорошие задачи. Причем, там есть система проверки ответа. Загружаете программу на сайт и она там тестируется
автоматически.
0
SergioO
95 / 184 / 63
Регистрация: 13.12.2015
Сообщений: 999
07.01.2016, 17:53  [ТС] #13
Цитата Сообщение от Nosey Посмотреть сообщение
Прочитайте краткий пересказ: Единица трансляции
вот который раз убеждаюсь что наглядно должны такие вопросы разбираться - как говорил Пуанкаре:"чтобы объяснить обыкновенные дроби нужен нож и торт". на словах все это, особенно новичку мало понятно. вот бы схемкой как типа "мультик" )) "лежит" файлик и тут компилятор его берет и что дальше происходит, что куда включается и не включается... сам бы уже такую фигню сделал, но я подобными пакетами не владею. не хотите заняться? ))

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

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

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

Вот это ещё можно добавить к верхнему списку ссылок:
Компилятор - С++ использует раздельную компиляцию.
0
hoggy
6654 / 2842 / 487
Регистрация: 15.11.2014
Сообщений: 6,294
Завершенные тесты: 1
07.01.2016, 18:03 #15
Цитата Сообщение от Nosey Посмотреть сообщение
Мы не просим компилятор, мы лишь даём ему такую возможность,
нет, мы именно что просим.
все методы определённые в декларации класса неявно помечаются inline
1
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
07.01.2016, 18:03
Привет! Вот еще темы с ответами:

Подключение заголовочных файлов - C++
Здравствуйте. Возникают ошибки при компиляции проекта: 1. Указывает на указатель: 2. Указывает на указатель и коллекцию указателей: ...

Иерархия заголовочных файлов - C++
Вопрос такой. Есть 2 заголовочных файла с классами: core.h interface.h В core.h происходит #include interface.h В...

Назначение заголовочных файлов - C++
Я читала учебник и википедию - никак не доходит. В общем, может я неправильно поняла: есть у меня &quot;Моя программа.cpp&quot;, и есть...

Объявление заголовочных файлов - C++
Скажите в чем разница между объявлением вида: #include &lt;iostream&gt; и вида #include &quot;iostream&quot;


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

Или воспользуйтесь поиском по форуму:
15
Yandex
Объявления
07.01.2016, 18:03
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru