关于头文件重复包含以及函数重定义问题

来源:互联网 发布:mac vmware win10 编辑:程序博客网 时间:2024/05/02 02:08

 

调试的问题出现这个问题还蛮奇怪的,a.h需包含statistic.h, main.c需包含a.h和statistic.h,导致了statistic.h重复包含,hsdm_queue_ctr重复定义。

 关于重复包含和重复定义的问题,可根据下面的分析得到认识。

 为什么用了宏名字定义检测头文件的重复包含可还是有重复定义的错误?

我在一个头文件中定义了一个函数F, 整个头文件用:

#ifndef _XXX   #define _XXX...#endif

括起来以避免重复包含. 然后有两个Cpp文件都包含了这个头文件.编译无错,链接时却显示函数F被重复定义了(在其它文件中均没有重复定义这个F). 我把其中那个报错的Cpp文件里关于这个头文件的所有内容(对它的包含,对其中函数的调用)都注释掉以后编译, 再把注释去掉重新编译链接,就又无错了.   这到底是什么道理? 该怎样使它不被重复定义?

【todototry】:你放在头文件,对于使用文件而言确实未重复包含

但对整个工程而言,每个使用这个头文件的cpp文件编译生成的obj文件中均编译出了这个函数的实体,这样整个工程链接的时候,报信息

【todototry】:所以//name.h文件

#ifndef NAME_H#define NAME_H

函数声明

#endif

//name.cpp文件

函数定义

【chenqiu1024】:有点明白了. 可还不太明白, 我可能是还不懂编译器实际处理的方式:

1. #ifndef...#define...#endif这种方式是不是仅对一个CPP文件有用,就是说可以避免一个CPP文件已经#include了一个头文件,但又#include了另一个已经#include这个头文件的头文件?

2. 为什么用了这种方法,在头文件中定义的结构体或变量不会被认为重复定义,只有函数会报错呢?

【akirya:重复包含是编译期间的

#ifndef...#define...#endif这个只能解决重复包含,但无法解决重复定义的

重复定义是链接期间的

【chenqiu1024】那是不是说, 为避免重复定义, 结构体的定义和静态数据的定义也不能放在头文件里?

【todototry】:结构体的定义和静态数据的定义也不能放在头文件里?

这个你这么理解即可:你办定义可以呢看成两种:类型定义,数据定义

类型定义不分配内存的,比如类的定义,结构体的定义,它是定义一个数据类型而已,数据定义分配内存,比如类对象定义,变量定义

一个原则:不分配内存的,放在头文件    分配内存的放在cpp文件,放置重复定义

综上所述,你就可以知道结构体的定义属于类型定义放在头文件,静态数据的定义属于数据定义放在cpp文件.对于函数相同,函数声明你可以看作类型定义,函数实现看作数据定义

因为两个 cpp 是相对独立的,A 包含 h 文件和 B 包含h文件没有关系,

也就是 #ifndef...#define...#endi 并没有起到效果 ...

如果是 A 包含B, B包含了 h , 那么可能会起到效果...

 

【jixingzhong】:一般 h 中都是声明,不是定义, 包括数据类型的声明以及函数原型的声明。

对于函数,然后使用一个对应名字的 .cpp 文件完成函数的定义,然后将这个 .cpp 添加到当前工程。在其他文件调用这个函数时候,include h 文件而不是 cpp 文件就可以了,这样就不会重复定义了 ...

多个程序公用一个头文件时头文件的定义是要小心的。容易造成重复定义。 
头文件里不要定义变量
,采用 extern 声明你的变量和函数。如: 
#define HASLABEL 1 
#define ISFIELD 0 
extern UInt cursor; 
//在其他文件里定义 
extern BooleanStrIsNum( CharPtr str ); 
//在其他文件里定义 
把函数声明(不是定义)放在公用头文件里不会有什么问题。 
全局变量确实不宜放在header里面定义,如果被多于一个的.c(cpp)引用,就会出现multiple definition。 
可以在一个.c里面定义,其它要用的.c前面extern 
但如果全局变量太多,也有一个办法可以放在头文件里: 
例如有三个.c文件:aaa.c, bbb.c和ccc.c 
在all.h里: 
#ifndef_defined_here_ 
#define EXT extern 
#else 
#define EXT 
#endif 
EXT int aaa; 
EXT float bbb; 
... 
然后在其中一个.c里加一句 
#define_defined_here_ 
就可以了 
另外注意,如:yyy.h  yyy.c,在yyy.h中对函数的声明默认就是extern的。
加不加上extern,都无所谓,但是yyy.h定义了的变量,如果这个yyy.h被多个.c调用就会出现重复定义,所以变量放yyy.c中定义,在yyy.h中用extern int xxx外部声明就可以了。还有就是yyy.h中定义的函数同时把函数体也实现了,如:void setB(int a){b=a;},当被多个.c文件引用时也会出现重复定义的错误。。
今天就遇到这个问题,郁闷了半天,终于搞定了,以前都用c++写程序,没大多涉及到函数,全局变量的调用,没注意过这种问题。这些天用c写的代码多了,居然出了一大堆问题,习惯了OO编程,还真不习惯c程序,老觉得不好用。


---下面是在网上搜到的谈到头文件定义问题的一些东西---------------------
例如:
我在程序中建立一个globle.h文件,代码如下:
#ifndef  _GLOBLE_H
#define  _GLOBLE_H
int   a;
int   b;
int   c;
#endif
有多个.cpp文件引用他,编译的时候说变量重复定义,可是我已经加入了#ifndef这样的语句.

解决方法1:
改成:
#ifndef    _GLOBLE_H   
#define    _GLOBLE_H   
extern  int     a;   
extern  int     b;   
extern  int     c;   
#endif   
并在其中的一个cpp文件里加上
int    a;   
int    b;   
int    c;   
解决方法2:
/*
  *  FILENAME:   Global.h
  *  PURPOSE   :   Global   Variabels.
  *  global   定义前缀使用说明:
  *  很多程序将所有的全局变量放在一个文件中定义,然后在另一个头文件中进行
  *  声明(加extern修饰).  如var_main.h定义变量,var.h声明变量,这种方法在有
  *  大量变量的情况下,可能会造成两个文件不一致,从而引起潜在的问题.
  *
  *  采用global预编译指令,只要在main.c文件包含其他的头文件之前加入
  *  #define   _MAIN_DEFINE_
  *  #include   "global.h"
  *  #include   "otherfile.h"   ,
  *  那么编译器将在这个文件中定义变量,在其他文件中只作声明,不会重复定义.
  */
#ifndef  _GLOBAL_H_   
#define  _GLOBAL_H_
#ifdef  _MAIN_DEFINE_   
#define  global     
#else
#define  global   extern
#endif  //   _MAIN_DEFINE_
//////////////////////    全局类型     /////////////////////////////////
typedef  enum   
{
       E_SUCC        =   0,
       E_COMM_FAIL   =   1,
}  ERESULT;
//////////////////////    全局变量     /////////////////////////////////
////    需要初始化的全局变量
#ifdef  _MAIN_DEFINE_   
// global  int   g_nInit   =   ArrayArray;
#else    //   just   extern
// global  int   g_nInit   ;
#endif  //   _MAIN_DEFINE_
////    不需要初始化的全局变量
global long    g_lTrace;
//////////////////////    全局函数     /////////////////////////////////
void  g_fun(void);
#endif  //   _GLOBAL_H_
当然,如果项目比较大的话,应该把函数申明和类型、结构的定义分别放到其他文件中,再在global.h中引
入,如:
#include  "func.h"
#include  "macro.h"
#include  "struct.h" 

0 0
原创粉丝点击