浅谈头文件(.h)和源文件(.cpp)的区别

本人原来在大一写C的时候,都是所有代码写在一个文件里一锅乱煮。经过自己开始写程序之后,发现一个工程只有一定是由多个不同功能、分门别类展开的文件构成的。一锅乱煮只会导致代码可读性差、维护性差。但是本人在学习C++的时候,被这章节弄混了。 Source & Header, Separate Files from Classes,里面介绍了一个对于Python写手来说很新的概念。就是头文件和源文件的区别,下面谈谈我自己学习后的理解。

头文件(.h)

头文件用来写 类的声明 (包括类的成员的声明和方法声明)、函数原型#define 常数等,但是很少会写出具体的实现和细节。就好比抽象类一样。

头文件很有意思的是,开头和结尾必须按照以下格式:

#ifndef MYCLASS_H
#define MYCLASS_H // code here #endif

当时我看到这个是极其的不理解和迷茫的,后来阅读了别人的博文才略懂。

首先解释他是干嘛使的,这是防止头文件被重复引用。什么叫被重复引用?就是同一个头文件(.h)在同一个源文件(.cpp)中被include了多次。这种错误常常是因为include嵌套。举个最简单的例子,存在cellphone.h这个头文件引用了#include "huawei.h",之后又有china.cpp这个源文件同时导入了#include "cellphone.h" 和 #include "huawei.h"。此时huawei.h就在一个源文件里引用了两次。

那么,某些时候,只是因为include了两遍,增大了编译器的工作量。如果是小型程序的话还好说,但是大型工程甚至会增长几个小时的编译时间。但是另一些情况,会引起很严重的错误。比如在头文件中定义了全局变量会引起重复定义。

所以就有了我们上面那些看起来乱七八糟的代码,下面开始解释。

#ifndef MYCLASS_H 的意思是 if not define myclass.h,这样看就很好理解了,如果引用这个头文件的源文件不存在myclass.h这个头文件,那么接下行 #define MYCALSS_H, 引入myclass.h。然后就是我们头文件的代码。如果已经有了,直接跳到 #endif。

理论上来说,上面这个片段的MYCLASS_H是可以任意命名的,但是约定俗成的,为了可读性的,我们都把它命名为这个头文件的大写和下划线的形式。如下面这一段代码:

#ifndef HUAWEI_H       // 防止huawei.h被重复引用
#define HUAWEI_H #include <cmath> // 引用标准库
#include "honor.h" // 引用非标准库头文件
...
void Function(); // 全局函数声明
class Mate20{ // 类声明
public: Mate20(); // 构造函数声明
~Mate20(); // 析构函数声明
private:
protected:
}; #endif

上面的代码其实已经很好的解释了头文件的作用——声明。可以看见内部的函数和方法仅仅是声明,而都没有写入具体细节。

源文件(.cpp)

源文件主要写实现头文件中已经声明的那些函数的具体代码。需要注意的是,开头必须#include一下实现的头文件,以及要用到的头文件。那么当你需要用到自己写的头文件中的类时,只需要#include进来就行了。

下面举个例子

我首先写一个头文件Pen.h,里面定义了一个Pen类:

#ifndef PEN_H
#define PEN_H
#include <string>
class Pen
{
public:
Pen(std::string brand); }; #endif

然后我在我的主文件test.cpp中引入了这个头文件:

#include <iostream>
#include "Pen.h"
using namespace std; Pen::Pen(string brand) {
cout << "What brand are you looking for?" << endl;
cout << brand;
} int main() {
Pen pilot("pilot"); } // 输出结果为
/* What brand are you looking for?
pilot */

结果表明,这样引入是正确的。

浅谈头文件(.h)和源文件(.cpp)的区别的更多相关文章

  1. C++中的头文件(.h)和源文件(.cpp)都应该写什么?

    头文件(.h):写定义和声明写类的声明(包括类里面的成员和方法的声明).函数原型.#define常数等,但是一般来说不写具体的实现.注意: 1.在写头文件的时候需要注意,在开头和结尾处必须按照如下样式 ...

  2. 浅谈Linux下/etc/passwd文件

    浅谈Linux 下/etc/passwd文件 看过了很多渗透测试的文章,发现在很多文章中都会有/etc/passwd这个文件,那么,这个文件中到底有些什么内容呢?下面我们来详细的介绍一下. 在Linu ...

  3. 视频基础知识:浅谈视频会议中H.264编码标准的技术发展

    浅谈视频会议中H.264编码标准的技术发展 浅谈视频会议中H.264编码标准的技术发展 数字视频技术广泛应用于通信.计算机.广播电视等领域,带来了会议电视.可视电话及数字电视.媒体存储等一系列应用,促 ...

  4. 浅谈JAVA GUI中,AWT与Swing的区别、联系及优缺点

    浅谈JAVA GUI中,AWT与Swing的区别.联系及优缺点 A.区别 1.发布的时间 AWT是在JDK 1.0版本时提出的 Swing是在AWT之后提出的(JAVA 2) 2. ”重量” AWT是 ...

  5. 浅谈Oracle中物理结构(数据文件等。。。)与逻辑结构(表空间等。。。。。)

    初始Oracle时很难理解其中的物理结构和逻辑结构,不明白内存中和硬盘中文件的区别和联系,我也是初学Oracle,这里就简单的谈谈我我看法. 首先,你需要明白的一点是:数据库的物理结构是由数据库的操作 ...

  6. 浅谈hadoop中mapreduce的文件分发

    近期在做数据分析的时候.须要在mapreduce中调用c语言写的接口.此时就须要把动态链接库so文件分发到hadoop的各个节点上,原来想自己来做这个分发,大概过程就是把so文件放在hdfs上面,然后 ...

  7. 头文件 .h 与源文件 .ccp 的区别

    .h 文件一般是用来定义的,比如定义函数.类.结构体等: .cpp 文件则是对头文件的定义进行实现. include .h文件,可以调用你声明的函数.类等.当然,比较简单的类.函数,你也可以直接在头文 ...

  8. 浅谈2D游戏设计模式2- WZ文件详解(UI.WZ)之MapLogin.img(1)

    玩过冒险岛的人都知道有一个WZ文件,那么这个WZ文件的内部是怎么样的呢,今天我就带大家一探究竟. 说实在的,我这是第一次接触WZ文件,但是却让我很震撼,为什么很震撼,因为这个居然是用VS2010写的! ...

  9. 浅谈odoo 后台与前端文件(附件)的存储与下载

    odoo 后台与前端文件(附件)存储与下载实现 笔记太多了很乱,想想还是写博客的好,慢慢更 当然了,前提是你已经配好了odoo开发环境 一.odoo后台界面实现附件的上传和下载 1).在应用中搜索下图 ...

随机推荐

  1. 写一个scrapy中间件--ip代理池

    middleware文件 # -*- coding: utf-8 -*- # Define here the models for your spider middleware # See docum ...

  2. [转载]Linux服务器丢包故障的解决思路及引申的TCP/IP协议栈理论

    Linux服务器丢包故障的解决思路及引申的TCP/IP协议栈理论 转载至:https://www.sdnlab.com/17530.html 我们使用Linux作为服务器操作系统时,为了达到高并发处理 ...

  3. 解决mongo单文档超过16M

    mongodb导入大文件的数据时,导入一小部分后,提示lost connect,失去连接.mongo文件有6.3G,网上查了一下,原来Mongo对单次处理好像有大小限制(16m),所以大文件会出问题, ...

  4. MQTT抓包分析

    1. 概述 MQTT(Message Queuing Telemetry Transport,消息队列遥测传输协议),是一种基于发布/订阅(Publish/Subscribe)模式的轻量级通讯协议,该 ...

  5. gradle管理的Springboot使用JSP详解

    大家知道现在的springboot默认经不支持jsp了,但是还是可以用的,需要加一些配置. 我使用的springboot是用gradle构造的,现在跟着我一步步来吧! 一,新建一个springBoot ...

  6. 关于MySQL数据库事务的机制学习总结

    这几天面试多次被问到了数据库事务机制.隔离级别.乐观锁悲观锁类的问题,之前对这些只能说有所了解,有些概念还停留在记忆层面,没有理解,所以回答的不好.后面翻书学习了下,理解了一些东西,在此做一个记录. ...

  7. Shell 截取字符串方法

    原文链接 方法1 "${varible##*string}" 从左向右截取最后一个string后的字符串 e.g. exampleString="abc//888//ab ...

  8. zookeeper基础学习-简介

    1.zookeeper的使命 zookeeper可以在分布式系统的协作多个任务(一个任务是指一个包含多个进程的任务),这个任务可以是为了协作或者是为了管理竞争. 协作:多个进程需要一同处理某些事情,一 ...

  9. Java中内部类和静态内部类的区别

    内部类和静态内部类 示例 public class OuterClass { private int numPrivate = 1; public int numPublic = 2; public ...

  10. android 练习效果(界面一)