淺談#ifndef,#define,#endif的作用和用法
問(wèn)題:ifndef/define/endif”主要目的是防止頭文件的重復(fù)包含和編譯
========================================================
用法:
.h文件,如下:
#ifndef XX_H
#define XX_H
...
#endif
這樣如果有兩個(gè)地方都包含這個(gè)頭文件,就不會(huì)出現(xiàn)兩次包含的情況 。。
因?yàn)樵诘诙伟瑫r(shí) XX_H 已經(jīng)有定義了,所以就不再 include了
-------------------------------------------------------
#ifndef GRAPHICS_H // 防止graphics.h被重復(fù)引用 #define GRAPHICS_H #include <math.h> // 引用標(biāo)準(zhǔn)庫(kù)的頭文件 … #include “myheader.h” // 引用非標(biāo)準(zhǔn)庫(kù)的頭文件 … void Function1(…); // 全局函數(shù)聲明 … class Box // 類結(jié)構(gòu)聲明 { … }; #endif
-----------------------------------------------------
那是指你建立多個(gè)文件時(shí),多個(gè)文件里都包含這個(gè)頭文件
-----------------------------------------------------
給你舉個(gè)例子,再順便分析一下:
假設(shè)你的工程里面有4個(gè)文件,分別是a.cpp,b.h,c.h,d.h
a.cpp的頭部是:
#include "b.h "
#include "c.h "
b.h和c.h的頭部都是:
#include "d.h "
而d.h里面有class D的定義。
這樣一來(lái),
編譯器編譯a.cpp的時(shí)候,先根據(jù)#include "b.h "去編譯b.h這個(gè)問(wèn)題,再根據(jù)b.h里面的#include "d.h ",去編譯d.h的這個(gè)文件,這樣就把d.h里面的class D編譯了;
然后再根據(jù)a.cpp的第二句#include "c.h ",去編譯c.h,最終還是會(huì)找到的d.h里面的class D,但是class D之前已經(jīng)編譯過(guò)了,所以就會(huì)報(bào)重定義錯(cuò)誤。
加上ifndef/define/endif,就可以防止這種重定義錯(cuò)誤。
--------------------------------------------------
-------------------------------------------------
1.比如你有兩個(gè)C文件,這兩個(gè)C文件都include了同一個(gè)頭文件。而編譯時(shí),這兩個(gè)C文件要一同編譯成一個(gè)可運(yùn)行文件,于是問(wèn)題來(lái)了,大量的聲明沖突。 還是把頭文件的內(nèi)容都放在#ifndef和#endif中吧。
不管你的頭文件會(huì)不會(huì)被多個(gè)文件引用,你都要加上這個(gè)。
一般格式是這樣的:
#ifndef <標(biāo)識(shí)>
#define <標(biāo)識(shí)>
......
......
#endif <標(biāo)識(shí)>
在理論上來(lái)說(shuō)可以是自由命名的,但每個(gè)頭文件的這個(gè)“標(biāo)識(shí)”都應(yīng)該是唯一的。標(biāo)識(shí)的命名規(guī)則一般是頭文件名全大寫,前后加下劃線,并把文件名中的“.”也變成下劃線,如:stdio.h
#ifndef _STDIO_H_ #define _STDIO_H_ ...... #endif
2.在#ifndef中定義變量出現(xiàn)的問(wèn)題(一般不定義在#ifndef中)。
#ifndef AAA
#define AAA
...
int i;
...
#endif
里面有一個(gè)變量定義在vc中鏈接時(shí)就出現(xiàn)了i重復(fù)定義的錯(cuò)誤,而在c中成功編譯。
原因:
(1).當(dāng)你第一個(gè)使用這個(gè)頭的.cpp文件生成.obj的時(shí)候,int i 在里面定義了當(dāng)另外一個(gè)使用這個(gè)的.cpp再次[單獨(dú)]生成.obj的時(shí)候,int i 又被定義然后兩個(gè)obj被另外一個(gè).cpp也include 這個(gè)頭的,連接在一起,就會(huì)出現(xiàn)重復(fù)定義.
(2).把源程序文件擴(kuò)展名改成.c后,VC按照C語(yǔ)言的語(yǔ)法對(duì)源程序進(jìn)行編譯,而不是C++。在C語(yǔ)言中,若是遇到多個(gè)int i,則自動(dòng)認(rèn)為其中一個(gè)是定義,其他的是聲明。
(3).C語(yǔ)言和C++語(yǔ)言連接結(jié)果不同,可能(猜測(cè))在進(jìn)行編譯的時(shí)候,C++語(yǔ)言將全局變量默認(rèn)為強(qiáng)符號(hào),所以連接出錯(cuò)。C語(yǔ)言則依照是否初始化進(jìn)行強(qiáng)弱的判斷的。
參考解決方法:
(1).把源程序文件擴(kuò)展名改成.c。
(2).推薦解決方案: .h中只聲明 extern int i;
在.cpp中定義
#ifndef __X_H__
#define __X_H__
extern int i;
#endif //__X_H__ int i;
注意問(wèn)題:變量一般不要定義在.h文件中。
以上就是小編為大家?guī)?lái)的淺談#ifndef,#define,#endif的作用和用法全部?jī)?nèi)容了,希望大家多多支持腳本之家~
相關(guān)文章
C++實(shí)現(xiàn)雷霆戰(zhàn)機(jī)可視化小游戲
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)雷霆戰(zhàn)機(jī)可視化小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11C++實(shí)現(xiàn)四則混合運(yùn)算計(jì)算器
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)四則混合運(yùn)算計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-11-11通俗易懂講解C語(yǔ)言與Java中二叉樹的三種非遞歸遍歷方式
二叉樹是一種非常重要的數(shù)據(jù)結(jié)構(gòu),很多的數(shù)據(jù)結(jié)構(gòu)都是基于二叉樹的基礎(chǔ)演變過(guò)來(lái)的。二叉樹的前,中,后3種遍歷方式,因?yàn)闃涞亩x本身就是遞歸定義的,所以采用遞歸的方法來(lái)實(shí)現(xiàn)是很簡(jiǎn)單的2021-09-09C++ OpenCV實(shí)戰(zhàn)之形狀識(shí)別
本案例通過(guò)使用OpenCV中的approxPolyDP進(jìn)行多邊形近似,進(jìn)而進(jìn)行基礎(chǔ)形狀識(shí)別(圓、三角形、矩形、星形…),快跟隨小編一起動(dòng)手嘗試一下2022-07-07C++?Boost?CircularBuffer算法超詳細(xì)精講
Boost是為C++語(yǔ)言標(biāo)準(zhǔn)庫(kù)提供擴(kuò)展的一些C++程序庫(kù)的總稱。Boost庫(kù)是一個(gè)可移植、提供源代碼的C++庫(kù),作為標(biāo)準(zhǔn)庫(kù)的后備,是C++標(biāo)準(zhǔn)化進(jìn)程的開發(fā)引擎之一,是為C++語(yǔ)言標(biāo)準(zhǔn)庫(kù)提供擴(kuò)展的一些C++程序庫(kù)的總稱2022-11-11