# รวมใน. 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?
Owen S.

คำตอบ:


161

ใส่ให้มากที่สุดเท่าที่จะ.cทำได้ในไฟล์.h. การรวมในไฟล์.cจะรวมเฉพาะเมื่อไฟล์นั้นถูกคอมไพล์เท่านั้น แต่การรวมสำหรับไฟล์.hนั้นจะต้องถูกรวมไว้ในทุกไฟล์ที่ใช้


6
จริง แต่#ifndef _CALLBACK_H_ด้านบนของมันป้องกันไม่ให้คอมไพเลอร์ประมวลผลมากกว่าหนึ่งครั้งหรือไม่?
hytromo

11
@ user9379 ซึ่งจะป้องกันไม่ให้รวมมากกว่าหนึ่งครั้งต่อไฟล์. c หรือ. cpp โดยทั่วไปไฟล์. c หรือ. cpp แต่ละไฟล์จะสร้างทีละไฟล์ซึ่งหมายความว่าไฟล์. h จะถูกแยกวิเคราะห์ใหม่สำหรับไฟล์. c หรือ. cpp แต่ละไฟล์ที่คุณคอมไพล์
Brendan Long

2
ฉันคิดว่าเหตุผลหลักที่ต้องใส่ให้น้อยที่สุดเท่าที่จะเป็นไปได้.hคือเพื่อหลีกเลี่ยงข้อผิดพลาดในบางกรณีเนื่องจากการรวมเข้าด้วยกัน ตัวอย่าง: คลาสสองคลาสต้องการกันและกันสำหรับการนำไปใช้งาน แต่ไม่ใช่สำหรับการประกาศ การใส่ทั้งสองอย่างใน.cpps จะหลีกเลี่ยงข้อผิดพลาด
Codoscope

1
@ Qu'est-cet'yont นั่นเป็นเหตุผลว่าทำไมคุณไม่สามารถใส่บางสิ่งลงในไฟล์. h ได้ คำตอบนี้เกี่ยวกับเหตุผลที่คุณควรใส่น้อยกว่านั้น
Brendan Long

@BrendanLong ฉันเห็นแม้ว่าในความหมายของฉันการรวมส่วนหัวเดียวกันหลายครั้งไม่สำคัญว่าคุณจะใส่มาโครที่ถูกต้องไว้ข้างในเพื่อรวมเนื้อหาเพียงครั้งเดียว ดังนั้นฉันคิดว่าการใส่ให้น้อยลงคือการลดความน่าจะเป็นที่จะได้รับข้อผิดพลาดในอนาคตด้วยการแก้ไขโค้ด
Codoscope

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 ก่อนส่วนหัว); นั่นคือความอิจฉาริษยากองใหญ่ที่รอให้เกิดขึ้น ฉันหมายถึงมัน ฉันเคยดูหนังเรื่องนั้นมาหลายครั้งแล้วและมันมักจะจบลงด้วยเปลวเพลิงของโตเกียว

ใช่สิ่งนี้อาจส่งผลให้มีการรวมไฟล์หลายครั้ง แต่หากมีการตั้งค่ายามรวมไว้อย่างเหมาะสมเพื่อป้องกันข้อผิดพลาดในการประกาศ / คำจำกัดความหลายครั้งเวลาในการสร้างเพิ่มอีกไม่กี่วินาทีก็ไม่คุ้มที่จะต้องกังวล การพยายามจัดการการพึ่งพาด้วยตนเองเป็นความเจ็บปวดที่ตูด

แน่นอนคุณไม่ควรรวมไฟล์ที่คุณไม่จำเป็นต้องใช้


10

ใส่ include ใน cpp ของคุณให้มากที่สุดและเฉพาะสิ่งที่จำเป็นสำหรับไฟล์ hpp ใน hpp ฉันเชื่อว่าสิ่งนี้จะช่วยเร่งความเร็วในการรวบรวมเนื่องจากไฟล์ hpp จะถูกอ้างอิงข้ามน้อยลง

ลองพิจารณาใช้การประกาศไปข้างหน้าในไฟล์ hpp ของคุณเพื่อลดห่วงโซ่การรวมการพึ่งพา


1
Oo สิ่งที่ประกาศไปข้างหน้านั้นน่าสนใจ
Brendan Long

Parappa การประกาศไปข้างหน้ามีประโยชน์มากในสถานการณ์อ้างอิงแบบวงกลม แต่จะเป็นแนวทางปฏิบัติที่ดีในสถานการณ์อื่น ๆ หรือไม่? (ฉันใหม่ใน C ++ ดังนั้นฉันจึงถามอย่างจริงใจ)
Dzyann

5

ถ้าฉัน#include <callback.h>ฉันไม่ต้องการที่จะต้องใช้#includeไฟล์ส่วนหัวอื่น ๆ จำนวนมากเพื่อรับโค้ดของฉันไปคอมไพล์ ในcallback.hคุณควรจะรวมถึงทุกอย่างที่จำเป็นในการรวบรวมกับมัน แต่ไม่มีอะไรมาก.

พิจารณาว่าการใช้การประกาศไปข้างหน้าในไฟล์ส่วนหัวของคุณ (เช่นclass GtkButton;) จะเพียงพอหรือไม่ทำให้คุณสามารถลดจำนวน#includeคำสั่งในส่วนหัว (และในทางกลับกันเวลาในการรวบรวมและความซับซ้อนของฉัน)


ฉันไม่เห็นด้วย. การรวมโลกทั้งใบไว้ในไฟล์ H จะเพิ่มห่วงโซ่การพึ่งพาและเวลาในการคอมไพล์
John Dibling

คำตอบของฉันไม่ได้ขอแนะนำให้รวมถึงทั่วโลกในไฟล์ส่วนหัวผมแนะนำรวมถึงเพียงเพียงพอเพื่อให้ผู้ใช้ของ API ไม่ต้องใช้เวลาในการค้นหาอ้างอิง
Johnsyweb
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.