1、#ifndef #define #endif头文件保护符

在编译的过程中,每个.cpp文件被看成一个单独的文件来编译成单独的编译单元,#ifndef 保证类的头文件在同一个.cpp文件里被多次引用后不会出现重定义问题。

注意:仅仅是防止在同一个.cpp文件里被多次引用。

样例:

// file1.h
class file1
{
}; // file2.h
#include "file1.h"
class file2
{
}; // file3.h
#include "file1.h"
#include "file2.h"

file3.h展开来是这种:

// file1.h展开的内容
class file1
{
};
// file2.h展开的内容
class file1
{
};
class file2
{
};

这时候就会出现重定义了,假设在每一个文件加上#ifndef头文件保护符:

// file1.h
#ifndef _FILE1_H_
#define _FILE1_H_ class file1
{
}; #endif // !_FILE1_H_
// file2.h
#ifndef _FILE2_H_
#define _FILE2_H_ #include "file1.h"
class file2
{
}; #endif // !_FILE2_H_
// file3.h
#ifndef _FILE3_H_
#define _FILE3_H_ #include "file1.h"
#include "file2.h" #endif // !_FILE3_H_

这时候展开file3.h时,由于_FILE1_H_仅仅会被定义一次。所以就不会出现重定义错误。

2、变量的声明和定义

定义:用于为变量分配存储空间,还能够为变量指定初始值。在一个程序中,变量有且仅有一个定义。

声明:用于向程序表明变量的类型和名字。在一个程序中。声明能够有多个。定义也是声明:当定义变量时我们声明了它的类型和名字。能够通过使用externkeyword声明变量名而不定义它:extern int i;。

样例:

// file1.h
#ifndef _FILE1_H_
#define _FILE1_H_ int a = 1; #endif // !_FILE1_H_
// file2.h
#ifndef _FILE2_H_
#define _FILE2_H_ #include "file1.h" #endif // !_FILE2_H_
// main.cpp
#include <iostream> int main()
{
extern int a;
std::cout << a << std::endl; system("pause");
return 0;
}

这时候编译会报错,由于在file1.h定义了a。在file2.h的展开中又定义了a。

有人会问。#ifndef不是防止重定义的吗?#ifndef是防止在同一个文件的重定义,在上面的情况,file1.h和file2.h是两个不同的文件。所以会在file1.h和file2.h同一时候出现int a = 1,就出现重定义错误了。

所以不要在头文件定义变量,最好的做法是:在头文件声明变量,在.cpp定义变量,在须要使用该变量的地方先声明再使用。

改动下上面的样例:

// file1.h
#ifndef _FILE1_H_
#define _FILE1_H_ extern int a; #endif // !_FILE1_H_
// file1.cpp
#include "file1.h" int a = 1;
// file2.h
#ifndef _FILE2_H_
#define _FILE2_H_ #include "file1.h" #endif // !_FILE2_H_

main.cpp不变。这时候就能够正常执行了。

3、能够在头文件定义的三个例外

(1)类的定义。

类的定义很多其它像是声明,由于此时并没有分配空间。

(2)值在编译时就已知的const对象。

如:const char c = 'c';,这个是在编译时就已经确定值的。之后程序不能改变。

而const char *c = 'c';是不能够的,由于指针不是在编译时确定值的。

(3)inline内联函数。

C++头文件保护符和变量的声明定义的更多相关文章

  1. c++类模板中静态成员变量的声明定义

    我们知道,c++中,类的静态成员是要在.cpp文件中定义的,如果在.h中定义,会出现重复定义. 但是在写类模板时,一般所有的代码都是放在.h文件中的,如果要做分离是一件很麻烦的事.那如果出现了静态成员 ...

  2. 预处理器&预处理变量&头文件保护&条件编译

    [常见的预处理功能] #include 头文件保护符 条件编译 [预处理器] 编译之前执行的一段程序,可以部分地改变我们所写的程序 举个例子:当预处理器看到#include标记时就会用指定的头文件的内 ...

  3. C++ 多文件编译简述:头文件、链接性、声明与定义

    目录 Commen Sense 头文件 链接性 static 与链接性控制 extern 与外部链接性 Reference Commen Sense C++ 在编译时对每个翻译单元(Translati ...

  4. javascript中的函数式声明与变量式声明

    观察下面两段代码,试写出hello('word');的运行结果: // 变量式声明 function hello(msg){ alert(msg); var msg = function(){}; a ...

  5. 变量的声明和定义以及extern的用法

    变量的声明和定义以及extern的用法                                          变量的声明不同于变量的定义,这一点往往容易让人混淆. l         变量 ...

  6. C++解析头文件-Qt自动生成信号声明

    目录 一.瞎白话 二.背景 三.思路分析 四.代码讲解 1.类图 2.内存结构声明 3.QtHeaderDescription 4.私有函数讲解 五.分析结果 六.下载 一.瞎白话 时间过的ZTMK, ...

  7. 在源文件(.c)和头文件(.h)中声明和定义的区别——C语言

    最近在看多文件编程的时候遇到的一个问题,本来以为理解了声明和定义的区别(然而并没有····),也算是重新认识了一次声明和定义,下面上代码 情形一:在源文件(.c)中 相信大部分读者对声明和定义的理解是 ...

  8. C基础知识(2):变量&常量的定义和声明

    变量定义和声明 (1) 使用int,char等类型符定义变量 使用int,char等类型符定义变量时,不管有没有指定初始值,都就已经建立了存储空间(开辟内存).内存寻址由大到小,优先分配内存地址比较大 ...

  9. MFC中成员变量的声明顺序与析构顺序

    第一次用博客,第一篇随笔,就写今天遇到的一个问题吧. 在VS2008的MFC对话框程序,窗口成员变量的声明顺序与其析构顺序相反,即,先声明的变量后析构,后声明的变量先析构.未在其他模式下测试. cla ...

随机推荐

  1. 使用 boost 进行 CRC32 校验

    使用 boost 进行 CRC32 校验 - firebird321的专栏 - 博客频道 - CSDN.NET 使用 boost 进行 CRC32 校验 分类: 文件操作 2008-06-06 18: ...

  2. HashSet的排序

    import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util ...

  3. win7下让程序默认以管理员身份运行

    在win7中用自己写的程序读取MBR时,突然提示无法对磁盘进行操作,而在xp下并没有这个问题:最后点右键以管理员身份运行才可以正常运行.于是想办法让程序在双击启动时默认以管理员身份运行.具体方法: 1 ...

  4. gcc和g++的区别【转自中国源码网】

    gcc和g++的区别[转自中国源码网] gcc和g++都是GNU(组织)的一个编译器. 误区一:gcc只能编译c代码,g++只能编译c++代码两者都可以,但是请注意:1.后缀为.c的,gcc把它当作是 ...

  5. apache的开源项目-模板引擎(Velocity)(转)

    然后修改conf文件下的server.xml文件,在server.xml里的           <Connector port="8080" .... />字段后   ...

  6. SQL中如何将一个表中的某一列的数据复制到另一个表中的某一列里

    表一: SPRD PRD_NO      SPC 001                NULL 002               NULL 003               NULL ...   ...

  7. Delphi使用大图标编译程序

    在Windows Vista. Windows7以上Windows系统中可以支持大图标显示了,但是Delphi编译出来的程序却只能显示32x32的图标,这使Delphi编译的程序看起来很不专业.下面就 ...

  8. [Android学习笔记]ShareSDK的使用

    ShareSDK使用方便,集成简单,正式客户端开发人员的首选组件 集成步骤,使用说明见官方文档: http://wiki.sharesdk.cn/Android_快速集成指南 记录: 直接使用官方De ...

  9. [Cocos2d-x]Mac下运行HelloCpp For Android

    2013年12月22日 一.简介: Mac下运行Cocos2d-x的samples和新建的HelloCocos2dx项目 二.内容: 环境: OS:mac OS X 10.9.1 IDE:Androi ...

  10. POJ2584 T-Shirt Gumbo【二分图多重匹配】

    题目链接: id=2584">http://poj.org/problem?id=2584 题目大意: 如今有5种型号(S.M.L.X.T)的衣服要发放给N个參赛队员.给出每一个參赛者 ...