C++中头文件的概念与基本编写方法

1 标准库中的头文件
C++标准库中的一切内容都被放在名字空间std中(名字空间中的内容对外是不可见的),但是带来了一个新问题,无数现有的C++代码都依赖于使用了多年的伪标准库中的功能,如声明在<iostream.h>等头文件中的功能,使用std包装标准库导致现有代码的不可用,为了兼容这种情况,标准委员会为包装了std的那部分标准库创建了新的头文件,新的头文件的文件名与旧的一样,只是没有.h这个后缀,如<iostream.h>就变成了<iostream>。对于C头文件,采用同样的方法,但还在每个头文件名前加了字符c,如<string.h>就变成了<cstring>,<stdio.h>变成了<cstdio>。最好使用新的文件头,使用新的文件头的C++程序,需要使用using namespace std或者using namespace std::指定的类名,等方法来使需要的类对于我们的代码可视。

2 自定义的头文件
为了防止头文件被重复引用,最好使用预处理定义,如下所示:

#ifndef MYHEAD_H
#define MYHEAD_H
……//头文件中的内容
#endif

(1)#ifndef:
   指示符#ifndef用来检查头文件的内容是否在前面已经被定义过,如果定义过,则#ifndef与#endif之间的语句将不被执行.所以习惯上要把头文件的定义写在这两个语句之间.
如:对于MYHEAD.H这个头文件

#ifndef MYHEAD_H
#define MYHEAD_H

#include "myhead.h"

  ......

#endif

(2) #ifdef
  指示符#ifdef常常被用来判断一个预处理器常量是否已被定义,以便有条件地包含程序代码。
如:

 int main()
 {
  #ifdef DEBUG
  cout<<"Beginning execution of main()\n";
  #endif
  string word;
  vector<string> text;
  while(cin>>word)
  {
 #ifdef DEBUG
 cout<<"word read:"<<word<<"\n";
 #endif
 text.push_back(word);
  }
 //..... }

在此程序中,如果定义了DEBUG,则其中包含的两个语句都将被执行,如果没有定义,则其中的两个输出语句不被执行。

3 预处理相关知识
(1) #ifdef :判断一个预处理常量是否被定义,如#infef DEGUG
(2) #ifndef:判断一个预处理常量是否没被定义
(3) #define:定义一个预处理常量,如#define DEBUG
(4) #include
(5) #endif
(6) 对预处理常量的定义还可以在编译时进行,如CC –D DEBUG main.c
(7)编译C++程序时,编译器自动定义了一个预处理器名字__cplusplus(注意前面有两个下划线),因此可以根据这个来判断该程序是否是C++程序,以便有条件地包含一些代码,如:

#ifndef MYHEAD_H
#define MYHEAD_H
#ifdef __cplusplus
extern "C" {
#endif
int DMpostprocessing();
#ifdef __cplusplus
}
#endif
#endif

(8)在编译C程序时,编译器会自动定义预处理常量__STDC__。当然__cplusplus和__STDC__ 不会同时被定义;
(9)另外两个比较有用的预定义常量是__LINE__(记录文件已经被编译的行数)和__FILE__(包含正在被编译的文件名称)。使用如下:

if(element_count==0)
 cerr<<"Error:"<<__FILE__
   <<":line"<<__LINE__
   <<"element_count must be non-zero.\n";

(10) __DATE__:编译日期,当前被编译文件的编译日期
(11) __TIME__:编译时间,当前被编译文件的编译时间
格式如:hh:mm:ss

08:17:05   Oct 31 2006
(12) C库头文件的C++名字总是以字母C开头,后面去掉.h,如assert.h在C++中为cassert;

assert()是C语言标准库中提供的一个通用预处理器宏。常用其来判断一个必需的前提条件,以便程序能够正确执行。与其关联的头文件是:#include <assert.h>
如:

 assert(filename!=0);

表示:如果后面的程序能够正确执行,需要filename不为0,如是条件为假,即其等于0,断言失败,则程序将输出诊断消息,然后终止。

其c++名字是:cassert
C库头文件的C++名字总是以字母C开头
注:在C++中使用C标准库中的头文件时,一定要使用using namespace std;来使其处在一个名字空间中,才能正确使用

(13)在C++中头文件后缀各不相同,因此标准的C++头文件没有指定后缀

4 C++中的文件输入输出

头文件:#include <fstream>

使用文件输入输出实例:

 #include <fstream>
//为了打开一个输出文件,先声明一个ofstream类型的对象:
 ofstream outfile("name-of-file");
//为了测试是否已经成功打开了一个文件,如下判断:
 //如文件不能打开值为false
 if(!outfile)
   cerr<<"Sorry! We were unable to open the file!\n";

//为了打开一个输入文件,先声明一个ifstream类型的对象:
  ifstream infile("name of file");
  if(!infile)
   cerr<<"Sorry! We were unable to open the file!\n";

一个简单程序:
  #include <iostream>
  #include <fstream>
  #include <string>

  int main()
  {
   ofstream outfile("out_file");
 ifstream infile("in_file");
 if(!infile){
   cerr<<"error:unable to open input file!\n";
   return -1;
 }
 if(!outfile) {
   cerr<<"error:unable to open output file!\n";
   return -2;
 }
 string word;
 while (infile>>word)
  outfile<<word<<' ';
 return 0;
  }

头文件里有些什么?
头文件的使用主要体现在两个方面,一个是重(音chóng)用(即多次使用),另一个是共用。

那些提供标准库函数的头文件就是为了重用。很多程序或工程可能会用到这些标准库函数,把它们写在头文件里面,每次使用的时候只需要包含已经完成的头文件就可以了。

头文件的共用主要体现在C++的多文件结构中。由于目前的程序规模较小,尚不需要用到多文件结构,所以在此对头文件的共用不作展开。有兴趣的读者可以查阅相关书籍。
那么,如果我们要自己编写一个可以重用的头文件,里面应该写些什么呢?

类似于标准库函数,我们在头文件里面应该模块化地给出一些函数或功能。另外还应该包括独立实现这些函数或功能的常量、变量和类型的声明。

下面我们就来看一个头文件应用的实例:

//shape.h
#include "math.h"//在计算三角形面积时要用到正弦函数
const double pi=3.14159265358;//常量定义
struct circle//类型声明
{
  double r;
};
struct square
{
  double a;
};
struct rectangle
{
  double a,b;
};
struct triangle
{
  double a,b,c,alpha,beta,gamma;
};
double perimeter_of_circle(double r)//函数定义
{
  return 2*pi*r;
}
double area_of_circle(double r)
{
  return pi*r*r;
}
double perimeter_of_square(double a)
{
  return 4*a;
}
double area_of_square(double a)
{
  return a*a;
}
double perimeter_of_rectangle(double a,double b)
{
  return 2*(a+b);
}
double area_of_rectangle(double a,double b)
{
  return a*b;
}
double perimeter_of_triangle(double a,double b,double c)
{
  return a+b+c;
}
double area_of_triangle(double a,double b,double gamma)
{
  return sin(gamma/180*pi)*a*b/2;
}
//main.cpp
#include "iostream.h"
#include "shape.h"//包含我们编写好的shape.h
int main()
{
  circle c={2};
  square s={1};
  rectangle r={2,3};
  triangle t={3,4,5,36.86989,53.13011,90};
  cout <<"Perimeter of circle " <<perimeter_of_circle(c.r) <<endl;
  cout <<"Area of square " <<area_of_square(s.a) <<endl;
  cout <<"Perimeter of rectangle " <<perimeter_of_rectangle(r.a,r.b) <<endl;
  cout <<"Area of triangle " <<area_of_triangle(t.b,t.c,t.alpha) <<endl;
  return 0;
}

运行结果:

Perimeter of circle 12.5664
Area of square 1
Perimeter of rectangle 10
Area of triangle 6

我们编写好了shape.h头文件,以后用到计算图形周长或面积的时候,就不需要重新编写函数了,只需要包含这个头文件就行了。

(0)

相关推荐

  • C++常用的#include头文件总结

    本文详细罗列了C++所包含的头文件的名称及作用说明,比较适合初学者了解一下,几乎每一个C++文件的开始都要#include ,可大部分人都没有去关注#include 后面是什么,对照本文的说明相信会对大家理解C++结构多少有些帮助. #include <deque> //STL 双端队列容器 #include <exception> //异常处理类 #include <fstream> //文件输入/输出 #include <functional> //ST

  • C++ 学习之旅二 说一说C++头文件

    一.C++头文件究竟是什么,你怎么看? 每个C++/C程序通常分为两个文件.一个文件用于保存程序的声明(declaration),称为头文件.另一个文件用于保存程序的实现(implementation),称为定义(definition)文件.C++/C程序的头文件以".h"为后缀,C程序的定义文件以".c"为后缀,C++程序的定义文件通常以".cpp"为后缀(像linux等系统以".cc"或".cxx"为后

  • 浅析VC++中的头文件包含问题

    在一些大的工程中,可能会包含几十个基础类,免不了之间会互相引用(不满足继承关系,而是组合关系).也就是需要互相声明.好了,这时候会带来一些混乱.如果处理得不好,会搞得一团糟,根据我的经验,简单谈谈自已的处理办法: 编码时,我们一般会尽量避免include头文件,而是采用声明 class XXX.但有时候还是必须用Include头文件,那么,两者的划分在于什么呢? 应该是很明确的,但书上好像都少有提及. 首先:我们要明白为什么要用声明取代头文件包含:对了,是为了避免无必要的重编译(在头文件发生变更

  • 简单谈谈C++ 头文件系列之(algorithm)

    简介 algorithm头文件是C++的标准算法库,它主要应用在容器上. 因为所有的算法都是通过迭代器进行操作的,所以算法的运算实际上是和具体的数据结构相分离的 ,也就是说,具有低耦合性. 因此,任何数据结构都能使用这套算法库,只要它具有相应的迭代器类型. 算法类别 如上图所示,库中的算法主要分为4类: 非修改性顺序操作(Non-modifying sequence operations) 可变顺序操作(Mutating sequence operations) 排序和关系操作(Sorting

  • C++中头文件和源文件详细介绍

    C++中的头文件和源文件详解 一.C++编译模式 通常,在一个C++程序中,只包含两类文件--.cpp文件和.h文件.其中,.cpp文件被称作C++源文件,里面放的都是C++的源代码:而.h文件则被称作C++头文件,里面放的也是C++的源代码. C+ +语言支持"分别编译"(separate compilation).也就是说,一个程序所有的内容,可以分成不同的部分分别放在不同的.cpp文件里..cpp文件里的东西都是相对独立的,在编 译(compile)时不需要与其他文件互通,只需要

  • VC++开发中完美解决头文件相互包含问题的方法解析

    所谓超前引用是指一个类型在定义之前就被用来定义变量和声明函数. 一般情况下,C/C++要求所有的类型必须在使用前被定义,但是在一些特殊情况下,这种要求无法满足,例如,在类CMyView中保留了一个非模式对话框对象指针,该对象用于显示/修改一些信息.为了实现对话框"应用"按钮,把对话框做的修改立刻更新到view界面上,为此,需要在对话框类中需要保存view类的指针,这样定义关系就变成如下的代码: 复制代码 代码如下: #ifndef __MYVIEW_H__   #define __MY

  • 简单谈谈C++ 头文件系列之(bitset)

    简介 该头文件有关位集,实际上是vector 位 位本质上对应bool的概念,只有0或1,true或false两种对立的值. 但很可惜,字节才是机器上最小的存储单元,所以bool基本上是由一个字节大小. bitset是出于高效的空间利用为目的才出现的. 位操作 operator [] : 通过下标访问bit. count : 计数位值为1的位个数. size : 返回位的大小,即有多少个位. test : 测试下标指向的位值是否为1. any : 判断是否有任何一个位值为1. none : 判断

  • C++中头文件的概念与基本编写方法

    1 标准库中的头文件 C++标准库中的一切内容都被放在名字空间std中(名字空间中的内容对外是不可见的),但是带来了一个新问题,无数现有的C++代码都依赖于使用了多年的伪标准库中的功能,如声明在<iostream.h>等头文件中的功能,使用std包装标准库导致现有代码的不可用,为了兼容这种情况,标准委员会为包装了std的那部分标准库创建了新的头文件,新的头文件的文件名与旧的一样,只是没有.h这个后缀,如<iostream.h>就变成了<iostream>.对于C头文件,

  • c++ 防止头文件重复引入的三种方法

    在之前我们详细介绍了 C 语言中如何使用宏定义(#ifndef / #define / #endif)来有效避免头文件被重复 #include,此方式在 C++ 多文件编程中也很常用. 举个例子,如下是一个 C++ 项目,其内部含有 school.h 和 student.h 这 2 个头文件以及 main.cpp 源文件,其各自包含的代码为: //student.h class Student {     //...... }; //school.h #include "student.h&qu

  • php获取数组元素中头一个数组元素值的实现方法

    本文实例讲述了php获取数组元素中头一个数组元素值的实现方法.分享给大家供大家参考.具体如下: 在php的内置函数中,获取数组元素值的函数主要有 reset next current prev end 这几个函数. reset (PHP 3, PHP 4, PHP 5) 函数定义:mixed reset ( array &array ) 作用:该函数将 array 的内部指针倒回到第一个单元并返回第一个数组单元的值,如果数组为空则返回 FALSE,代码如下: 复制代码 代码如下: $array=

  • linux shell 中判断文件、目录是否存在的方法

    本文主要介绍了linux shell 中判断文件.目录是否存在的方法,分享给大家 -e filename 如果 filename存在,则为真 -d filename 如果 filename为目录,则为真 -f filename 如果 filename为常规文件,则为真 -L filename 如果 filename为符号链接,则为真 -r filename 如果 filename可读,则为真 -w filename 如果 filename可写,则为真 -x filename 如果 filenam

  • C#/VB.NET 在PDF中添加文件包(Portfolio)的方法

    PDF文件包(Portfolio)允许用户将多种不同类型的文件如Word.Excel.PDF.PowerPoint和图片等集合到一个PDF文件中,用户可以打开.更改PDF文件包中的单个文件.添加文件包时,可支持创建文件包时并直接将文件添加到文件包:或者创建文件包的同时创建文件夹,并将文件添加到文件夹. 环境准备:程序中需要使用到PDF类库工具(Spire.PDF for .NET hotfix 6.5.15及以上版本)下载后,解压,将Bin文件夹下的dll文件添加引用到VS程序.如下效果: 1.

  • 详解JAVA中获取文件MD5值的四种方法

    JAVA中获取文件MD5值的四种方法其实都很类似,因为核心都是通过JAVA自带的MessageDigest类来实现.获取文件MD5值主要分为三个步骤,第一步获取文件的byte信息,第二步通过MessageDigest类进行MD5加密,第三步转换成16进制的MD5码值.几种方法的不同点主要在第一步和第三步上.具体可以看下面的例子: 方法一. private final static String[] strHex = { "0", "1", "2"

  • C++中头文件与源文件的作用详解

    一.C++ 编译模式 通常,在一个 C++ 程序中,只包含两类文件-- .cpp 文件和 .h 文件.其中,.cpp 文件被称作 C++ 源文件,里面放的都是 C++ 的源代码:而 .h 文件则被称作 C++ 头文件,里面放的也是 C++ 的源代码. C++ 语言支持"分别编译"(separatecompilation).也就是说,一个程序所有的内容,可以分成不同的部分分别放在不同的 .cpp 文件里..cpp 文件里的东西都是相对独立的,在编译(compile)时不需要与其他文件互通

  • Node.js HTTP服务器中的文件、图片上传的方法

    HTTP协议中,multipart/form-data格式用于向服务器发送二进制数据,通过这一内容类型(Content-Type)可以实现文件.图片的上传.由于这种格式发送的是二进制数据,在服务器端接收和处理数据时会与其它内容类型有所有区别. HTTP协议中的文件上传 最早的HTTP协议中是不支持文件上传的,在1995年制定的rfc1867规范中,在HTTP POST请求的内容类型Content-Type中扩展了multipart/form-data类型,该类型用于向服务器发送二进制数据,以便支

  • IIS 7 中设置文件上传大小限制设置方法

    在IIS 6.0中设置文件上传大小的方法,就是配置如下节点: 复制代码 代码如下: <system.web><httpRuntime maxRequestLength="1048576" executionTimeout="600"/>        </system.web> 但在IIS7中,设置如上设置后,不管设置多大数值,最大上传了限制为30M 还要进行如下设置才能正确: 方法1: appcmd set config &qu

随机推荐