• c++头文件包含 #ifndef ##pragma once


    2013-04-14 17:03 (分类:计算机程序)

          烦死了,这种垃圾小问题很多,你又必须要知道。。。。。。。在编写c++程序时,会编写多个类或者多个cpp文件,免不了要多次使用include包含头文件,于是重复包含的问题就来了,怎样避免这一情况呢?

           在此我们使用条件编译来解决这个问题

    #ifndef x //先测试x是否被宏定义过
    #define x

    程序段1     //如果x没有被宏定义过,定义x,并编译程序段1

    #endif

    程序段2     //如果x已经定义过了则编译程序段2的语句,“忽视”程序段1。

     

         条件指示符#ifndef 的最主要目的是防止头文件的重复包含和编译,#ifndef 和 #endif 要一起使用,如果丢失#endif,可能会报错。

           一般格式是这样的:
    #ifndef <标识>
    #define <标识>
    ............
    #endif<标识>
    ............

        在理论上来说可以是自由命名的,但每个头文件的这个“标识”都应该是唯一的。标识的命名规则一般是头文件名全大写,前面加下划线,并把文件名中的“.”也变成下划线,
    如:stdio.h
    #ifndef _STDIO_H_
    #define _STDIO_H_
    ......
    #endif 

     

     

          在高版本的VC++上,还可以使用这个命令来代替以上的所有:   #pragma once      它的意思是,本文件内的代码只被使用一次。
           Visual C++使用#pragma once来通知编译器在生成时只包含(打开)一次,也就是说,在第一次#include之后,编译器重新生成时不会再对这些包含文件进行包含(打开)和读取,因此我们看到在用向导创建的所有类的头文件中有#pragma once语句就不会觉得奇怪了。然而正是由于这个语句而造成了在第二次#include后编译器无法正确识别所引用的类。
         

    不要以为使用了这种机制就全部搞定了,比如在以下的代码中:

    //文件A.h中的代码
    #pragma once

    #include "B.h"

    class A{      
    public:       
       B* b;
             };

    //文件B.h中的代码
    #pragma once

    #include "A.h"

    class B{      
    public:       
       A* a;
           };

    这里两者都使用了指针成员,因此嵌套本身不会有什么问题,在主函数前面使用#include "A.h"之后,主要编译错误如下:      error C2501: 'A' : missing storage-class or type specifiers仍然是类型不能找到的错误。其实这里仍然需要前置声明。分别添加前置声明之后,可以成功编译了。代码形式如下:

    //文件A.h中的代码
    #pragma once

    #include "B.h"

    class B;       //前置声明类B

    class A{      
    public:    
          B* b;
    };

    //文件B.h中的代码
    #pragma once

    #include "A.h"

    class B;       //前置声明类B

    class B{    
      public:     
         A* a;
    };

     

          头文件包含其实是一想很烦琐的工作,不但我们看着累,编译器编译的时候也很累,再加上头文件中常常出现的宏定义。感觉各种宏定义的展开是非常耗时间的,远不如自定义函数来得速度。我仅就不同头文件、源文件间的句则结构问题提出两点原则,仅供参考:

        

          第一个原则应该是,如果可以不包含头文件,那就不要包含了。这时候前置声明可以解决问题。如果使用的仅仅是一个类的指针,没有使用这个类的具体对象(非指针),也没有访问到类的具体成员,那么前置声明就可以了。因为指针这一数据类型的大小是特定的,编译器可以获知。

          第二个原则应该是,尽量在CPP文件中包含头文件,而非在头文件中。假设类A的一个成员是是一个指向类B的指针,在类A的头文件中使用了类B的前置声明并编译成功,那么在A的实现中我们需要访问B的具体成员,因此需要包含头文件,那么我们应该在类A的实现部分(CPP文件)包含类B的头文件而非声明部分(H文件)。

     
  • 相关阅读:
    永远不要在MySQL中使用UTF8
    DevExpress 如何向lookUpEditor中添加新值
    DevExpress 如何向lookUpEditor中添加新值
    给DataTable中添加一行数据
    给DataTable中添加一行数据
    【VS】使用vs2017自带的诊断工具(Diagnostic Tools)诊断程序的内存问题
    【VS】使用vs2017自带的诊断工具(Diagnostic Tools)诊断程序的内存问题
    Winform开发的界面处理优化
    Winform开发的界面处理优化
    Linq扩展方法之All 、Any
  • 原文地址:https://www.cnblogs.com/centos2017/p/7896819.html
Copyright © 2020-2023  润新知