Это не обязательно избыточно. Тот факт, что у вас есть отдельные файлы заголовков и исходные файлы, означает, что вы можете менять местами файлы src и заголовочные файлы, если исходные файлы предоставляют определения для файлов заголовков.
.h файл должен включать только то, что используется в заголовке. Например, ему не нужен stdio, если в заголовке нет объявлений io, вместо этого он должен помещаться в файл src, только если он использует printf, например.
Но могут быть ситуации, когда один заголовок, который вы можете использовать, будет нуждаться в отдельном включении, в то время как другой заголовок не будет (например, когда один заголовок является более ограничительным интерфейсом, чем другой), и в этом случае лучше продублировать. ч включает.
Поскольку он защищен, он на самом деле не имеет никакого значения для конечного объекта / исполняемого файла, который вы создаете, и не увеличивает время компиляции из-за чего-то, о чем стоит беспокоиться, поэтому лучше включать их на тот случай, если вы захотите использовать другой .h файл в какой-то момент.
редактировать: более конкретный пример
inc1.h
#ifndef INC1_H
#define INC1_H
inc1_struct {
int x;
};
#endif
inc2.h
#ifndef INC2_H
#define INC2_H
#include "inc1.h"
void inc2_f();
struct inc1_struct *inc2_callinc1();
#endif
prog.cpp
#include "inc1.h"
#include "inc2.h"
#включают
#include
void inc2_f() {
printf("inc2_f\n");
}
struct inc1_struct *inc2_callinc1() {
return (struct inc1_struct*) malloc(sizeof(struct inc1_struct));
}
int main(int argc, char **argv) {
struct inc1_struct *s = inc2_callinc1();
return 0;
}
Это скомпилируется, но допустим, вы не хотите выставлять
struct inc1_struct *inc2_callinc1();
в inc2.h
Тогда вам не нужно будет включать inc1.h в файл inc2.h, но если вы не хотите также удалять определение inc2_callinc1 () в prog.cpp, вам нужно включить inc1. ч.