關於頭文件重複包含以及函數重定義問題

 

調試的問題出現這個問題還蠻奇怪的,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" 

發佈了50 篇原創文章 · 獲贊 13 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章