头文件中应该写什么

通 过上面的讨论,我们可以了解到,头文件的作用就是被其他的.cpp包含进去的。它们本身并不参与编译,但实际上,它们的内容却在多个.cpp文件中得到了 编译。通过定义只能有一次的规则,我们很容易可以得出,头文件中应该只放变量和函数的声明,而不能放它们的定义。因为一个头文件的内容实际上是会被引 入到多个不同的.cpp文件中的,并且它们都会被编译。放声明当然没事,如果放了定义,那么也就相当于在多个文件中出现了对于一个符号(变量或函数)的定 义,纵然这些定义都是相同的,但对于编译器来说,这样做不合法。

所以,应该记住的一点就是,.h头文件中,只能存在变量或者函数的声明, 而不要放定义。即,只能在头文件中写形如:extern int a;void f();的句子。这些才是声明。如果写上int a;或者void f() {}这样的句子,那么一旦这个头文件被两个或两个以上的.cpp文件包含的话,编译器会立马报错。
但是,这个规则是有三个例外的。

一,头文件中可以写const对象的定义。因为全局的const对象默 认是没有extern的声明的,所以它只在当前文件中有效。把这样的对象写进头文件中,即使它被包含到其他多个.cpp文件中,这个对象也都只在包含它的 那个文件中有效,对其他文件来说是不可见的,所以便不会导致多重定义。同时,因为这些.cpp文件中的该对象都是从一个头文件中包含进去的,这样也就保证 了这些.cpp文件中的这个const对象的值是相同的,可谓一举两得。同理,static对象的定义也可以放进头文件。

二,头文件中可 以写内联函数(inline)的定义。因为inline函数是需要编译器在遇到它的地方根据它的定义把它内联展开的,而并非是普通函数那样可以先声明再链 接的(内联函数不会链接),所以编译器就需要在编译时看到内联函数的完整定义才行。如果内联函数像普通函数一样只能定义一次的话,这事儿就难办了。因为在 一个文件中还好,我可以把内联函数的定义写在最开始,这样可以保证后面使用的时候都可以见到定义;但是,如果我在其他的文件中还使用到了这个函数那怎么办 呢?这几乎没什么太好的解决办法,因此C++规定,内联函数可以在程序中定义多次,只要内联函数在一个.cpp文件中只出现一次,并且在所有的.cpp文 件中,这个内联函数的定义是一样的,就能通过编译。那么显然,把内联函数的定义放进一个头文件中是非常明智的做法。

三,头文件中可以写类 (class)的定义。因为在程序中创建一个类的对象时,编译器只有在这个类的定义完全可见的情况下,才能知道这个类的对象应该如何布局,所以,关于类的 定义的要求,跟内联函数是基本一样的。所以把类的定义放进头文件,在使用到这个类的.cpp文件中去包含这个头文件,是一个很好的做法。在这里,值得一提 的是,类的定义中包含着数据成员和函数成员。数据成员是要等到具体的对象被创建时才会被定义(分配空间),但函数成员却是需要在一开始就被定义的,这也就 是我们通常所说的类的实现。一般,我们的做法是,把类的定义放在头文件中,而把函数成员的实现代码放在一个.cpp文件中。这是可以的,也是很好的办法。 不过,还有另一种办法。那就是直接把函数成员的实现代码也写进类定义里面。在C++的类中,如果函数成员在类的定义体中被定义,那么编译器会视这个函数为 内联的。因此,把函数成员的定义写进类定义体,一起放进头文件中,是合法的。注意一下,如果把函数成员的定义写在类定义的头文件中,而没有写进类定义中, 这是不合法的,因为这个函数成员此时就不是内联的了。一旦头文件被两个或两个以上的.cpp文件包含,这个函数成员就被重定义了。

在编多个头文件时,你应该遵循一些良好的编程实践,以保持代码的组织性和可维护性。以下是一些指导原则: 1. **组织头文件**:将相关的声明放在同一个头文件中。例如,如果你有一个`Stack`类和相关的类型定义和函数声明,它们都应该放在`Stack.h`文件中。 2. **使用预编译头文件**:为了避免头文件的重复包含导致编译时间增加,可以使用预编译头文件(通常用`.hpp`扩展名)。例如,你可以创建一个`Common.hpp`文件,包含所有项目通用的头文件,并在其他头文件中通过`#include "Common.hpp"`来引用它们。 3. **包含必要的头文件**:只包含当前文件需要的其他头文件。例如,如果一个头文件中声明的函数使用了另一个类,那么只需要包含那个类的头文件。 4. **使用`#ifndef`来防止头文件重复包含**:这是一种防止头文件被多次包含的常用技术。例如: ```cpp #ifndef STACK_H #define STACK_H // 头文件内容... #endif // STACK_H ``` 这将确保如果`Stack.h`被多次包含,其内容只会被编译一次。 5. **使用内联文件和声明**:对于简单的函数实现,可以在头文件中直接提供内联定义,这样可以减少编译依赖并加速编译过程。 6. **使用`extern`关键字**:如果在头文件中声明了全局变量,使用`extern`关键字来指示变量的定义在其他地方。 7. **保持头文件的自包含性**:一个头文件应该尽量能够独立存在,不应该依赖于其他头文件的顺序。 8. **避免在头文件定义静态成员变量**:静态成员变量应该在源文件中定义,而不是在头文件中,除非你有特殊的需求。 9. **使用引用传递而不是指针传递**:当你需要在头文件中传递大型对象时,使用引用可以避免不必要的复制,并且可以保证传递的是同一个对象。 遵循这些原则可以帮助你编清晰、高效和可维护的多个头文件
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值