#include в .h або .c / .cpp?


118

При кодуванні в C або C ++, де я маю їх #include?

callback.h:

#ifndef _CALLBACK_H_
#define _CALLBACK_H_

#include <sndfile.h>
#include "main.h"

void on_button_apply_clicked(GtkButton* button, struct user_data_s* data);
void on_button_cancel_clicked(GtkButton* button, struct user_data_s* data);

#endif

callback.c:

#include <stdlib.h>
#include <math.h>

#include "config.h"

#include "callback.h"
#include "play.h"

void on_button_apply_clicked(GtkButton* button, struct user_data_s* data) {
  gint page;
  page = gtk_notebook_get_current_page(GTK_NOTEBOOK(data->notebook));

  ...

Чи все повинно бути або в .h, або .c / .cpp, або в обох, як я робив тут?


2
Дозвольте мені це перевернути і запитаю: які були ваші критерії для вирішення розмістити sndfile.h та main.h у callback.h?
Оуен С.

Відповіді:


161

Покладіть стільки, скільки зможете в, .cі якомога менше в .h. Включає в the .c, включається лише тоді, коли складається один файл, але включає в себе для .hкожного, хто ним користується.


6
Щоправда, але чи не #ifndef _CALLBACK_H_перешкоджає компілятор обробляти його не один раз?
hytromo

11
@ user9379 Це запобіжить його включенню не раз у файл .c або .cpp. Кожен файл .c або .cpp, як правило, будується індивідуально, але це означає, що .h буде переаналізований для кожного .c або .cpp-файлу, який ви компілюєте.
Брендан Лонг

2
Я думаю, що головна причина, щоб якомога менше вкладати у це .h- уникнути в деяких випадках помилки через цикл включення. Приклад: два класи потрібні один одному для їх реалізації, але не для їх декларацій. Якщо поставити обидва включені в .cpps, ви уникнете помилки.
Кодоскоп

1
@ Qu'est-cet'yont Це причина, чому ви не можете помістити певні речі у файли .h. Ця відповідь стосується того, чому слід ставити ще менше.
Брендан Лонг

@BrendanLong Я бачу, хоча, з мого сенсу, включаючи кілька разів один і той же заголовок не має значення, якщо ви помістите правильні макроси всередину, щоб вміст включив лише один раз. Тому я думаю, що додавати ще менше - це зменшити ймовірність отримати помилку в майбутньому з модифікаціями коду.
Кодоскоп

55

Єдиний раз, коли ви повинні включити заголовок в інший .h-файл, якщо вам потрібно отримати доступ до визначення типу в цьому заголовку; наприклад:

#ifndef MY_HEADER_H
#define MY_HEADER_H

#include <stdio.h>

void doStuffWith(FILE *f); // need the definition of FILE from stdio.h

#endif

Якщо заголовок A залежить від заголовка B, такого як наведений вище приклад, тоді заголовок A повинен включати заголовок B безпосередньо. Як НЕ намагатися замовити ваш включає в .c файлі для задоволення залежностей (тобто, в тому числі заголовка B до заголовка A); це велика куча печії, яка чекає цього. Я мав це на увазі. Я був у тому фільмі кілька разів, і він завжди закінчувався з Токіо полум'ям.

Так, це може призвести до того, що файли включаються кілька разів, але якщо у них є належні захисні пристрої, встановлені для захисту від помилок декларування / визначення, то кілька додаткових секунд часу складання не варто турбуватися. Намагання керувати залежностями вручну - це біль в дупі.

Звичайно, ви не повинні включати файли там, де вам не потрібно .


10

Помістіть у ваш cpp якомога більше включень і лише ті, які потрібні файлу hpp у hpp. Я вважаю, що це допоможе прискорити компіляцію, оскільки файли hpp будуть менше перехресних посилань.

Також розглянути можливість використання переадресації у вашому файлі hpp для подальшого зменшення ланцюга включення залежності.


1
Оо. Цікава річ декларацій цікава.
Брендан Лонг

Parappa, прямі декларації дуже корисні в кругових довідкових сценаріях. Але чи були б вони гарною практикою в інших сценаріях? (Я
новачка

5

Якщо я #include <callback.h>, я не хочу мати #includeбагато інших файлів заголовків, щоб отримати свій код для компіляції. У callback.hвас слід включити все необхідне для складання проти нього. Але більше нічого.

Поміркуйте, чи class GtkButton;буде достатньо використання оголошень переадресації у файлі заголовка (такого як ), що дозволяє зменшити кількість #includeдиректив у заголовку (і, у свою чергу, час моєї компіляції та складність).


Я не погоджуюсь. Включення всього світу до файлів H збільшує ланцюг залежностей і, отже, час компіляції.
Джон Дайбілж

Моя відповідь не рекомендую включати весь світ в заголовки, я запропонував включити тільки досить так , щоб користувач API не доведеться витрачати час на пошук залежностей.
Johnsyweb
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.