1. 程式人生 > >C++類定義,.h檔案與.cpp檔案之間的關係以及條件編譯

C++類定義,.h檔案與.cpp檔案之間的關係以及條件編譯

大家有沒有考慮過,我們問什麼要將一個類定義和類實現分開呢?
本週的Windows程式設計課,老師演示了一個例子,完美地講解了這個問題,在我看來是解答了我一直以來的疑問,下面把我的一些體會整理在下面。

  • 使整個大的程式或者說專案顯得邏輯清晰、分明
  • 最重要的,也是老師在這堂課上展示出來的,就是在出現類組合這種情況,也就是類裡面的資料成員使用了其他類的物件的時候,如果不採用這種形式,就需要考慮很多哪個類放在前面這一類的問題,非常麻煩。

老師上課講的例子是這樣的:

#include <iostream>
using namespace std;

class A
{
private
: B b; public: void doSomething(); }; void A::doSomething() { b.doSomething(); } class B { public: void doSomething(); }; void B::doSomething() { cout<<"OK"<<endl; } int main(int argc, char *argv[]) { A * a = new A; a->doSomething(); return 0; }

上面的程式是否能通過編譯呢?答案當然是否定的。原因就在於A裡使用了B類的物件,又由於A類定義在前面,編譯器會不知道B究竟是什麼,自然也無法B b.
解決方法當然可以將類B定義在前面,也可以在類A定義前面加一句class B;

的前置宣告。但如果類變得更多,這樣就非常麻煩了。
另外,將類A中的B b改為B * b也可通過編譯,原因在於,B b的時候編譯器需要知道B究竟是什麼,只有這樣才能給它分配空間。而B * b的話,編譯器知道這是一個指標就足夠了,因為指標型別儲存一個地址,大小顯然是已知的。
因此,將類定義和類實現分開就顯得非常重要了。

  Windows程式設計課上,老師仔細講了.h和.cpp檔案。在將類定義和類實現分開的時候,遇到的問題可真不少。
  其中一個問題就是,A、B兩個類,A的資料成員有B的物件,在a.cpp裡我們要包含b.h,在mian裡我們要包含a.h和b.h,這時Qt Creator會報錯,提醒你出現了問題

E:\My_files\My_study\Computer_Science_2017-2018-2\windows programming\180516094934289_4thClassCode\4thClassCode\convertAandBtoHeader\b.h:4: error: redefinition of ‘class B’
class B
^

  顯示B被重複定義了。我們當然可以在main裡不寫#include “ b.h”,因為我們可以分析出這個已經在a.cpp裡出現,在#include “a.h”時會自己帶上。但是當類一多我們就記不清了,這時候就需要藉助巨集使用條件編譯。

#ifndef B_H
#define B_H
內容
#endif //B_H

  那麼作用是什麼呢?上面B_H可以任意的起名字,只是一個符號,表示這個符號如果還沒有被巨集定義的話,就定義它。這樣,當b.h已經被include過以後,B_H相當於已經被巨集定義過了,之後再被include,內容就不會再執行了,也就解決了問題。
C++的條件編譯還有其他的形式,具體用法為:
形式一:
#if 常量表達式
程式段
#endif
當常量表達式非零時編譯程式段
形式二:
#ifndef 常量表達式
程式段1
#else
程式段2
#endif
當常量表達式為非零時編譯程式段1,否則編譯程式段2
形式三:
#if 常量表達式1
程式段1
#elif 常量表達式2
程式段2
……
……
#elif 常量表達式n
程式段n
#else
程式段n+1
#endif
形式四:也就是最上面講的條件編譯

參考文獻:鄭莉等.C++語言程式設計[M].4版.北京:清華大學出版社,2010.
歡迎訪問我的網站——Luke的技術小站:http://119.23.31.14