程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> 關於C++ >> C++類的設計習慣及頭文件重復包含問題的解決

C++類的設計習慣及頭文件重復包含問題的解決

編輯:關於C++

在設計一個類的時候,通常是將類的定義及類成員函數的聲明放到頭文件(即.h文件)中,將類中成員函數的實現放到源文件(即.cpp)中。對於animal類需要animal.h和animal.cpp兩個文件,同樣,對於fish類需要fish.h和fish.cpp。對於main()函數,我們把它單獨放到EX10.cpp文件中。

往一個現有工程添加頭文件(.h文件)或源文件(.cpp文件)有兩種方式:一種是在打開的工程中,單擊【File】→【New】,在左邊的Files標簽頁下,選擇C++ Header File或C++ Source File,然後在右邊的File文本框中,輸入頭文件或源文件的文件名,如animal.h或animal.cpp,單擊【OK】按鈕。如圖2.16所示。

圖2.16 新建頭文件或源文件

另一種方式是在EX10的工程目錄下,單擊鼠標右鍵,選擇【新建】→【文本文檔】,然後將“新建文本文檔.txt”改名為“animal.h”(因.h和.cpp文件都是文本格式的文件),依同樣的方法,建立animal.cpp、fish.h、fish.cpp三個文件,然後在打開的工程中,選擇【Project】→【Add To Project】→【Files】,選擇animal.h、animal.cpp、fish.h、fish.cpp這四個文件,單擊【OK】按鈕,如圖2.17所示。

圖2.17 添加頭文件和源文件到工程中

代碼如例2-24所示。

例2-24

animal.h
  //在頭文件中包含類的定義及類成員函數的聲明
  class animal
  {
  public:
    animal();
    ~animal();
    void eat();
    void sleep();
    virtual void breathe();
  };
animal.cpp
  //在源文件中包含類中成員函數的實現
  #include "animal.h"     //因為在編譯animal.cpp時,編譯器不知道animal到底是什麼,所以要包含animal.h,這樣,編譯器就知道animal是一種類的類型
  #include <iostream.h>    //在包含頭文件時,<>和""有什麼區別?<>和""表示編譯器在搜索頭文件時的順序不同,<>表示從系統目錄下開始搜索,然後再搜索PATH環境變量所列出的目錄,不搜索當前目錄;
                ""是表示先從當前目錄搜索,然後是系統目錄和PATH環境變量所列出的目錄。所以如果我們知道頭文件在系統目錄下就可以直接用<>,這樣可以加快搜索速度
  animal::animal()      //::叫做作用域標識符,用於指明一個函數屬於哪個類或一個數據成員屬於哪個類。
::前面如果不跟類名,表示是全局
  {              函數(即非成員函數)或全局數據
  }
  animal::~animal()
  {
  }
  void animal::eat()     //注意:雖然我們在函數體中什麼也沒寫,但仍然是實現了這個函數
  {
  }
  void animal::sleep()
  {
  }
  void animal::breathe()   //注意,在頭文件(.h文件)中加了virtual後,在源文件(.cpp文件)中就不必再加virtual了
  {
    cout<<"animal breathe"<<endl;
  }
  fish.h
  #include "animal.h"     //因fish類從animal類繼承而來,要讓編譯器知道animal是一種類的類型,就要包含animal.h頭文件
  class fish:public animal
  {
  public:
     void breathe();
  };
  fish.cpp
  #include "fish.h"
  #include <iostream.h>
  void fish::breathe()
  {
    cout<<"fish bubble"<<endl;
  }
EX10.cpp
  #include "animal.h"
  #include "fish.h"
  void fn(animal *pAn)
  {
    pAn->breathe();
  }
  void main()
  {
    animal *pAn;
    fish fh;
    pAn=&fh;
    fn(pAn);
  }

現在我們就可以按下鍵盤上的F7功能鍵編譯整個工程了,編譯結果如下:

為什麼會出現類重復定義的錯誤呢?請讀者仔細查看EX10.cpp文件,在這個文件中包含了animal.h和fish.h這兩個頭文件。當編譯器編譯EX10.cpp文件時,因為在文件中包含了animal.h頭文件,編譯器展開這個頭文件,知道animal這個類定義了,接著展開fish.h頭文件,而在fish.h頭文件中也包含了animal.h,再次展開animal.h,於是animal這個類就重復定義了。

讀者可以測試一下,如果我們多次包含iostream.h這個頭文件,也不會出現上面的錯誤。要解決頭文件重復包含的問題,可以使用條件預處理指令。修改後的頭文件如下:

animal.h
  #ifndef ANIMAL_H_H   //我們一般用#define定義一個宏,是為了在程序中使用,使程序更加簡潔,維護更加方便,然而在此處,我們只是為了判斷
  #define ANIMAL_H_H   ANIMAL_H_H是否定義,以此來避免類重復定義,因此我們沒有為其定義某個具體的值。在選擇宏名時,要選用一些不常用的名字,
  class animal      因為我們的程序經常會跟別人寫的程序集成,如果選用一個很常用的名字(例如:X),有可能會造成一些不必要的錯誤
  {
  public:
     animal();
     ~animal();
     void eat();
     void sleep();
     virtual void breathe();
  };
  #endif
 fish.h
  #include "animal.h"
  #ifndef FISH_H_H
  #define FISH_H_H
  class fish:public animal
  {
  public:
     void breathe();
  };
  #endif

我們再看EX10.cpp的編譯過程。當編譯器展開animal.h頭文件時,條件預處理指令判斷ANIMAL_H_H沒有定義,於是就定義它,然後繼續執行,定義了animal這個類;接著展開fish.h頭文件,而在fish.h頭文件中也包含了animal.h,再次展開animal.h,這個時候條件預處理指令發現ANIMAL_H_H已經定義,於是跳轉到#endif,執行結束。

通過分析,我們發現在這次的編譯過程中,animal這個類只定義了一次。

提示:Windows 2000初始安裝完畢後,對於已知文件類型的擴展名是隱藏的,例如:“test.txt”這個文件,在資源浏覽器中看到的是“test”,在這種情況下,修改其文件名為“test.cpp”時,實際的文件名是“test.cpp.txt”,仍然是文本文件。因此在Win2000下做開發時,要取消“隱藏已知文件類型的擴展名”這一選項。

操作步驟:在資源浏覽器(或我的電腦)中,選擇菜單中的“工具->文件夾選項(O)…”,選擇“查看”標簽頁,將滾動欄拖到底端,將“隱藏已知文件類型的擴展名”復選框中的對號(√)取消掉,單擊“確定”按鈕。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved